home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.006 / xemacs-1 / lib / xemacs-19.13 / lisp / ediff / ediff-util.el < prev    next >
Encoding:
Text File  |  1995-08-31  |  114.2 KB  |  3,260 lines

  1. ;;; ediff-util.el --- the core commands and utilities of ediff
  2. ;;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
  3.  
  4. ;; Author: Michael Kifer <kifer@cs.sunysb.edu>
  5.  
  6. ;; This file is part of GNU Emacs.
  7.  
  8. ;; GNU Emacs is free software; you can redistribute it and/or modify
  9. ;; it under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation; either version 2, or (at your option)
  11. ;; any later version.
  12.  
  13. ;; GNU Emacs is distributed in the hope that it will be useful,
  14. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. ;; GNU General Public License for more details.
  17.  
  18. ;; You should have received a copy of the GNU General Public License
  19. ;; along with GNU Emacs; see the file COPYING.  If not, write to
  20. ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22.  
  23. ;;; Code:
  24.  
  25. (require 'ediff-init)
  26. (require 'ediff-meta)
  27.  
  28.  
  29. ;;; Functions
  30.  
  31. (defun ediff-mode ()
  32.   "Ediff mode controls all operations in a single Ediff session.
  33. This mode is entered through one of the following commands:
  34.     `ediff'
  35.     `ediff-files'
  36.     `ediff-buffers'
  37.     `ediff3'
  38.     `ediff-files3'
  39.     `ediff-buffers3'
  40.     `ediff-merge'
  41.     `ediff-merge-files'
  42.     `ediff-merge-files-with-ancestor'
  43.     `ediff-merge-buffers'
  44.     `ediff-merge-buffers-with-ancestor'
  45.     `ediff-merge-revisions'
  46.     `ediff-merge-revisions-with-ancestor'
  47.     `ediff-windows-wordwise'
  48.     `ediff-windows-linewise'
  49.     `ediff-regions-wordwise'
  50.     `ediff-regions-linewise'
  51.     `epatch'
  52.     `ediff-patch-file'
  53.     `ediff-patch-buffer'
  54.     `epatch-buffer'
  55.     `ediff-revision'
  56.  
  57. Commands:
  58. \\{ediff-mode-map}"
  59.   (kill-all-local-variables)
  60.   (setq major-mode 'ediff-mode)
  61.   (setq mode-name "Ediff")
  62.   (run-hooks 'ediff-mode-hooks))
  63.  
  64. (defun ediff-version ()
  65.   "Return string describing the version of Ediff.
  66. When called interactively, displays the version."
  67.   (interactive)
  68.   (if (interactive-p)
  69.       (message (ediff-version))
  70.     (format "Ediff %s of %s" ediff-version ediff-date)))
  71.     
  72.     
  73. (require 'ediff-diff)
  74. (require 'ediff-merg)
  75.   
  76.  
  77. ;;; Build keymaps
  78.  
  79. (ediff-defvar-local ediff-mode-map nil
  80.   "Local keymap used in Ediff mode.
  81. This is local to each Ediff Control Panel, so they may vary from invocation
  82. to invocation.")
  83.  
  84. ;; Set up the keymap in the control buffer
  85. (defun ediff-set-keys ()
  86.   "Set up Ediff keymap, if necessary."
  87.   (if (null ediff-mode-map)
  88.       (ediff-setup-keymap))
  89.   (use-local-map ediff-mode-map))
  90.   
  91. ;; Reload Ediff keymap.  For debugging only.
  92. (defun ediff-reload-keymap ()
  93.   (interactive)
  94.   (setq ediff-mode-map nil)
  95.   (ediff-set-keys))
  96.   
  97.  
  98. (defun ediff-setup-keymap ()
  99.   "Set up the keymap used in the control buffer of Ediff."
  100.   (setq ediff-mode-map (make-sparse-keymap))
  101.   (suppress-keymap ediff-mode-map)
  102.   
  103.   (define-key ediff-mode-map "p" 'ediff-previous-difference)
  104.   (define-key ediff-mode-map "\C-?" 'ediff-previous-difference)
  105.   (define-key ediff-mode-map [backspace] 'ediff-previous-difference)
  106.   (define-key ediff-mode-map [delete] 'ediff-previous-difference)
  107.   (define-key ediff-mode-map "\C-h" (if ediff-no-emacs-help-in-control-buffer
  108.                     'ediff-previous-difference nil))
  109.   (define-key ediff-mode-map "n" 'ediff-next-difference)
  110.   (define-key ediff-mode-map " " 'ediff-next-difference)
  111.   (define-key ediff-mode-map "j" 'ediff-jump-to-difference)
  112.   (define-key ediff-mode-map "g"  nil)
  113.   (define-key ediff-mode-map "ga" 'ediff-jump-to-difference-at-point)
  114.   (define-key ediff-mode-map "gb" 'ediff-jump-to-difference-at-point)
  115.   (define-key ediff-mode-map "q" 'ediff-quit)
  116.   (define-key ediff-mode-map "D" 'ediff-show-diff-output)
  117.   (define-key ediff-mode-map "z" 'ediff-suspend)
  118.   (define-key ediff-mode-map "\C-l" 'ediff-recenter)
  119.   (define-key ediff-mode-map "|" 'ediff-toggle-split)
  120.   (define-key ediff-mode-map "h" 'ediff-toggle-hilit)
  121.   (or ediff-word-mode
  122.       (define-key ediff-mode-map "@" 'ediff-toggle-autorefine))
  123.   (if ediff-narrow-job
  124.       (define-key ediff-mode-map "%" 'ediff-toggle-narrow-region))
  125.   (define-key ediff-mode-map "~" 'ediff-swap-buffers)
  126.   (define-key ediff-mode-map "v" 'ediff-scroll-vertically)
  127.   (define-key ediff-mode-map "\C-v" 'ediff-scroll-vertically)
  128.   (define-key ediff-mode-map "^" 'ediff-scroll-vertically)
  129.   (define-key ediff-mode-map "\M-v" 'ediff-scroll-vertically)
  130.   (define-key ediff-mode-map "V" 'ediff-scroll-vertically)
  131.   (define-key ediff-mode-map "<" 'ediff-scroll-horizontally)
  132.   (define-key ediff-mode-map ">" 'ediff-scroll-horizontally)
  133.   (define-key ediff-mode-map "i" 'ediff-status-info)
  134.   (define-key ediff-mode-map "E" 'ediff-documentation)
  135.   (define-key ediff-mode-map "?" 'ediff-toggle-help)
  136.   (define-key ediff-mode-map "!" 'ediff-update-diffs)
  137.   (define-key ediff-mode-map "M" 'ediff-show-meta-buffer)
  138.   (define-key ediff-mode-map "R" 'ediff-show-registry)
  139.   (or ediff-word-mode
  140.       (define-key ediff-mode-map "*" 'ediff-make-or-kill-fine-diffs))
  141.   (define-key ediff-mode-map "a"  nil)
  142.   (define-key ediff-mode-map "b"  nil)
  143.   (define-key ediff-mode-map "r"  nil)
  144.   (cond (ediff-merge-job
  145.      ;; Will barf if no ancestor
  146.      (define-key ediff-mode-map "/" 'ediff-show-ancestor)
  147.      ;; In merging, we allow only A->C and B->C copying.
  148.      (define-key ediff-mode-map "a" (function
  149.                      (lambda (arg)
  150.                        (interactive "P")
  151.                        (ediff-diff-to-diff arg "ac"))))
  152.      (define-key ediff-mode-map "b" (function
  153.                      (lambda (arg)
  154.                        (interactive "P")
  155.                        (ediff-diff-to-diff arg "bc"))))
  156.      (define-key ediff-mode-map "r" (function
  157.                      (lambda (arg)
  158.                        (interactive "P")
  159.                        (ediff-restore-diff arg ?c))))
  160.      (define-key ediff-mode-map "s" 'ediff-shrink-window-C)
  161.      (define-key ediff-mode-map "+" 'ediff-combine-diffs)
  162.      (define-key ediff-mode-map "$" 'ediff-toggle-show-clashes-only)
  163.      (define-key ediff-mode-map "&" 'ediff-re-merge))
  164.     (ediff-3way-comparison-job
  165.      (define-key ediff-mode-map "ab" 'ediff-diff-to-diff)
  166.      (define-key ediff-mode-map "ba" 'ediff-diff-to-diff)
  167.      (define-key ediff-mode-map "ac" 'ediff-diff-to-diff)
  168.      (define-key ediff-mode-map "bc" 'ediff-diff-to-diff)
  169.      (define-key ediff-mode-map "c" nil)
  170.      (define-key ediff-mode-map "ca" 'ediff-diff-to-diff)
  171.      (define-key ediff-mode-map "cb" 'ediff-diff-to-diff)
  172.      (define-key ediff-mode-map "ra" 'ediff-restore-diff)
  173.      (define-key ediff-mode-map "rb" 'ediff-restore-diff)
  174.      (define-key ediff-mode-map "rc" 'ediff-restore-diff)
  175.      (define-key ediff-mode-map "C"  'ediff-toggle-read-only))
  176.     (t ; 2-way comparison
  177.      (define-key ediff-mode-map "a" (function
  178.                      (lambda (arg)
  179.                        (interactive "P")
  180.                        (ediff-diff-to-diff arg "ab"))))
  181.      (define-key ediff-mode-map "b" (function
  182.                      (lambda (arg)
  183.                        (interactive "P")
  184.                        (ediff-diff-to-diff arg "ba"))))
  185.      (define-key ediff-mode-map "ra" 'ediff-restore-diff)
  186.      (define-key ediff-mode-map "rb" 'ediff-restore-diff))
  187.     ) ; cond
  188.   (define-key ediff-mode-map "G" 'ediff-submit-report)
  189.   (define-key ediff-mode-map "#"  nil)
  190.   (define-key ediff-mode-map "#h"  'ediff-toggle-regexp-match)
  191.   (define-key ediff-mode-map "#f"  'ediff-toggle-regexp-match)
  192.   (or ediff-word-mode
  193.       (define-key ediff-mode-map "##"  'ediff-toggle-skip-similar))
  194.   (define-key ediff-mode-map "o"   nil)
  195.   (define-key ediff-mode-map "A"  'ediff-toggle-read-only)
  196.   (define-key ediff-mode-map "B"  'ediff-toggle-read-only)
  197.   (define-key ediff-mode-map "w"   nil)
  198.   (define-key ediff-mode-map "wa"  'ediff-save-buffer)
  199.   (define-key ediff-mode-map "wb"  'ediff-save-buffer)
  200.   (define-key ediff-mode-map "wd"  'ediff-save-buffer)
  201.   (if ediff-3way-job
  202.       (progn
  203.     (define-key ediff-mode-map "wc" 'ediff-save-buffer)
  204.     (define-key ediff-mode-map "gc" 'ediff-jump-to-difference-at-point)
  205.     ))
  206.  
  207.   (define-key ediff-mode-map "m" 'ediff-toggle-wide-display)
  208.     
  209.   ;; Allow ediff-mode-map to be referenced indirectly
  210.   (fset 'ediff-mode-map ediff-mode-map)
  211.   (run-hooks 'ediff-keymap-setup-hooks))
  212.  
  213.  
  214. ;;; Setup functions
  215.  
  216. (require 'ediff-wind)
  217.  
  218. ;; Common startup entry for all Ediff functions
  219. ;; It now returns control buffer so other functions can do post-processing
  220. (defun ediff-setup (buffer-A file-A buffer-B file-B buffer-C file-C
  221.                  startup-hooks setup-parameters)
  222.   (setq file-A (expand-file-name file-A))
  223.   (setq file-B (expand-file-name file-B))
  224.   (if (stringp file-C)
  225.       (setq file-C (expand-file-name file-C)))
  226.   (let* ((control-buffer-name 
  227.       (ediff-unique-buffer-name "*Ediff Control Panel" "*"))
  228.      (control-buffer (ediff-eval-in-buffer buffer-A
  229.                (get-buffer-create control-buffer-name))))
  230.     (ediff-eval-in-buffer control-buffer
  231.       (ediff-mode)                 
  232.       
  233.       ;; unwrap set up parameters passed as argument
  234.       (while setup-parameters
  235.     (set (car (car setup-parameters)) (cdr (car setup-parameters)))
  236.     (setq setup-parameters (cdr setup-parameters)))
  237.     
  238.       ;; set variables classifying the current ediff job
  239.       (setq ediff-3way-comparison-job (ediff-3way-comparison-job)
  240.         ediff-merge-job (ediff-merge-job)
  241.         ediff-merge-with-ancestor-job (ediff-merge-with-ancestor-job)
  242.         ediff-3way-job (ediff-3way-job)
  243.         ediff-diff3-job (ediff-diff3-job)
  244.         ediff-narrow-job (ediff-narrow-job)
  245.         ediff-windows-job (ediff-windows-job)
  246.         ediff-word-mode-job (ediff-word-mode-job))
  247.     
  248.       (make-local-variable 'ediff-prefer-long-help-message)
  249.       (make-local-variable 'ediff-prefer-iconified-control-frame)
  250.       (make-local-variable 'ediff-split-window-function)
  251.       (make-local-variable 'ediff-default-variant)
  252.       (make-local-variable 'ediff-merge-window-share)
  253.       (make-local-variable 'ediff-window-setup-function)
  254.       
  255.       ;; adjust for merge jobs
  256.       (if ediff-merge-job
  257.       (let ((buf
  258.          ;; If default variant is `combined', the right stuff is
  259.          ;; inserted by ediff-do-merge
  260.          ;; Note: at some point, we tried to put ancestor buffer here
  261.          ;; (which is currently buffer C. This didn't work right
  262.          ;; because the merge buffer will contain lossage: diff regions
  263.          ;; in the ancestor, which correspond to revisions that agree
  264.          ;; in both buf A and B.
  265.          (cond ((eq ediff-default-variant 'default-B)
  266.             buffer-B)
  267.                (t buffer-A))))
  268.          
  269.         (setq ediff-split-window-function
  270.           ediff-merge-split-window-function) 
  271.         
  272.         ;; remember the ancestor buffer, if any
  273.         (setq ediff-ancestor-buffer buffer-C)
  274.         
  275.         (setq buffer-C
  276.           (get-buffer-create
  277.            (ediff-unique-buffer-name "*ediff-merge" "*")))
  278.         (save-excursion
  279.           (set-buffer buffer-C)
  280.           (insert-buffer buf)
  281.           (funcall (ediff-eval-in-buffer buf major-mode))
  282.           ;; after Stig@hackvan.com
  283.           (add-hook 'local-write-file-hooks 'ediff-set-merge-mode)
  284.           )))
  285.       (setq buffer-read-only nil    
  286.         ediff-buffer-A buffer-A
  287.         ediff-buffer-B buffer-B
  288.         ediff-buffer-C buffer-C
  289.         ediff-control-buffer control-buffer)
  290.        
  291.       (setq ediff-control-buffer-suffix
  292.         (if (string-match "<[0-9]*>" control-buffer-name)
  293.         (substring control-buffer-name
  294.                (match-beginning 0) (match-end 0))
  295.           "")
  296.         ediff-control-buffer-number
  297.         (max
  298.          0
  299.          (1-
  300.           (string-to-number
  301.            (substring
  302.         ediff-control-buffer-suffix
  303.         (or
  304.          (string-match "[0-9]+" ediff-control-buffer-suffix)
  305.          0))))))
  306.        
  307.       (setq ediff-error-buffer
  308.         (get-buffer-create (ediff-unique-buffer-name "*ediff-errors" "*")))
  309.       
  310.       (ediff-eval-in-buffer buffer-A (ediff-strip-mode-line-format))
  311.       (ediff-eval-in-buffer buffer-B (ediff-strip-mode-line-format))
  312.       (if ediff-3way-job
  313.       (ediff-eval-in-buffer buffer-C (ediff-strip-mode-line-format)))
  314.       (if (ediff-buffer-live-p ediff-ancestor-buffer)
  315.       (ediff-eval-in-buffer ediff-ancestor-buffer
  316.         (ediff-strip-mode-line-format)))
  317.       
  318.       (ediff-save-protected-variables) ; save variables to be restored on exit
  319.       
  320.       ;; ediff-setup-diff-regions-function must be set after setup
  321.       ;; parameters are processed.
  322.       (setq ediff-setup-diff-regions-function
  323.         (if ediff-diff3-job
  324.         'ediff-setup-diff-regions3
  325.           'ediff-setup-diff-regions))
  326.     
  327.       (setq ediff-wide-bounds
  328.         (list (ediff-make-bullet-proof-overlay
  329.            '(point-min) '(point-max) ediff-buffer-A)
  330.           (ediff-make-bullet-proof-overlay
  331.            '(point-min) '(point-max) ediff-buffer-B)
  332.           (ediff-make-bullet-proof-overlay
  333.            '(point-min) '(point-max) ediff-buffer-C)))
  334.       
  335.       ;; This has effect only on ediff-windows/regions
  336.       ;; In all other cases, ediff-visible-region sets visibility bounds to
  337.       ;; ediff-wide-bounds, and ediff-narrow-bounds are ignored.
  338.       (if ediff-start-narrowed
  339.       (setq ediff-visible-bounds ediff-narrow-bounds)
  340.     (setq ediff-visible-bounds ediff-wide-bounds))
  341.       
  342.       (ediff-set-keys) ; comes after parameter setup
  343.       
  344.       ;; set up ediff-narrow-bounds, if not set
  345.       (or ediff-narrow-bounds
  346.       (setq ediff-narrow-bounds ediff-wide-bounds))
  347.       
  348.       ;; All these must be inside ediff-eval-in-buffer control-buffer,
  349.       ;; since these vars are local to control-buffer
  350.       ;; These won't run if there are errors in diff
  351.       (ediff-eval-in-buffer ediff-buffer-A
  352.     (ediff-nuke-selective-display)
  353.     (run-hooks 'ediff-prepare-buffer-hooks)
  354.     (if (ediff-eval-in-buffer control-buffer ediff-merge-job)
  355.         (setq buffer-read-only t))
  356.     ;; add control-buffer to the list of sessions--no longer used, but may
  357.     ;; be used again in the future
  358.     (or (memq control-buffer ediff-this-buffer-ediff-sessions)
  359.         (setq ediff-this-buffer-ediff-sessions
  360.           (cons control-buffer ediff-this-buffer-ediff-sessions)))
  361.     )
  362.       (ediff-eval-in-buffer ediff-buffer-B
  363.     (ediff-nuke-selective-display)
  364.     (run-hooks 'ediff-prepare-buffer-hooks)
  365.     (if (ediff-eval-in-buffer control-buffer ediff-merge-job)
  366.         (setq buffer-read-only t))
  367.     ;; add control-buffer to the list of sessions
  368.     (or (memq control-buffer ediff-this-buffer-ediff-sessions)
  369.         (setq ediff-this-buffer-ediff-sessions
  370.           (cons control-buffer ediff-this-buffer-ediff-sessions)))
  371.     )
  372.       (if ediff-3way-job
  373.       (ediff-eval-in-buffer ediff-buffer-C
  374.         (ediff-nuke-selective-display)
  375.         (run-hooks 'ediff-prepare-buffer-hooks)
  376.         ;; add control-buffer to the list of sessions
  377.         (or (memq control-buffer ediff-this-buffer-ediff-sessions)
  378.         (setq ediff-this-buffer-ediff-sessions
  379.               (cons control-buffer
  380.                 ediff-this-buffer-ediff-sessions))) 
  381.         ))
  382.  
  383.       (if (ediff-buffer-live-p ediff-ancestor-buffer)
  384.       (ediff-eval-in-buffer ediff-ancestor-buffer
  385.         (ediff-nuke-selective-display)
  386.         (setq buffer-read-only t)
  387.         (run-hooks 'ediff-prepare-buffer-hooks)
  388.         (or (memq control-buffer ediff-this-buffer-ediff-sessions)
  389.         (setq ediff-this-buffer-ediff-sessions
  390.               (cons control-buffer
  391.                 ediff-this-buffer-ediff-sessions)))
  392.         ))
  393.       
  394.       ;; must come after setting up  ediff-narrow-bounds AND after
  395.       ;; nuking selective display
  396.       (funcall ediff-setup-diff-regions-function file-A file-B file-C)
  397.       (setq ediff-number-of-differences (length ediff-difference-vector-A))
  398.       (setq ediff-current-difference -1)
  399.       
  400.       (ediff-make-current-diff-overlay 'A)
  401.       (ediff-make-current-diff-overlay 'B)
  402.       (if ediff-3way-job
  403.       (ediff-make-current-diff-overlay 'C))
  404.       (if ediff-merge-with-ancestor-job
  405.       (ediff-make-current-diff-overlay 'Ancestor))
  406.       
  407.       (ediff-setup-windows buffer-A buffer-B buffer-C control-buffer)
  408.       
  409.       (let ((shift-A (ediff-overlay-start
  410.               (ediff-get-value-according-to-buffer-type
  411.                'A ediff-narrow-bounds)))
  412.         (shift-B (ediff-overlay-start
  413.               (ediff-get-value-according-to-buffer-type
  414.                'B ediff-narrow-bounds)))
  415.         (shift-C (ediff-overlay-start
  416.               (ediff-get-value-according-to-buffer-type
  417.                'C ediff-narrow-bounds))))
  418.     ;; position point in buf A
  419.     (save-excursion
  420.       (select-window ediff-window-A)
  421.       (goto-char shift-A))
  422.     ;; position point in buf B
  423.     (save-excursion
  424.       (select-window ediff-window-B)
  425.       (goto-char shift-B))
  426.     (if ediff-3way-job
  427.         (save-excursion
  428.           (select-window ediff-window-C)
  429.           (goto-char shift-C)))
  430.     )
  431.       
  432.       (select-window ediff-control-window)
  433.       (ediff-visible-region)
  434.       
  435.       (run-hooks 'startup-hooks)
  436.       (ediff-refresh-mode-lines)
  437.       (setq buffer-read-only t)
  438.       (setq ediff-session-registry
  439.         (cons control-buffer ediff-session-registry))
  440.       (ediff-update-registry)
  441.       (if (ediff-buffer-live-p ediff-meta-buffer)
  442.       (ediff-update-meta-buffer ediff-meta-buffer))
  443.       (run-hooks 'ediff-startup-hooks)
  444.       ) ; eval in control-buffer
  445.     control-buffer))
  446.       
  447.       
  448. ;; This function assumes that we are in the window where control buffer is
  449. ;; to reside. 
  450. (defun ediff-setup-control-buffer (ctl-buf)
  451.   "Set up window for control buffer."
  452.   (if (window-dedicated-p (selected-window))
  453.       (set-buffer ctl-buf) ; we are in control frame but just in case
  454.     (switch-to-buffer ctl-buf))
  455.   (let ((window-min-height 2))
  456.     (erase-buffer)
  457.     (ediff-set-help-message)
  458.     (insert ediff-help-message)
  459.     (shrink-window-if-larger-than-buffer)
  460.     (or (ediff-multiframe-setup-p)
  461.     (ediff-indent-help-message))
  462.     (set-buffer-modified-p nil)
  463.     (ediff-refresh-mode-lines)
  464.     (setq ediff-control-window (selected-window))
  465.     (setq ediff-window-config-saved
  466.       (format "%S%S%S%S%S%S%S"
  467.           ediff-control-window
  468.           ediff-window-A
  469.           ediff-window-B
  470.           ediff-window-C
  471.           ediff-split-window-function
  472.           (ediff-multiframe-setup-p)
  473.           ediff-wide-display-p))
  474.     (goto-char (point-min))
  475.     (skip-chars-forward ediff-whitespace)))
  476.     
  477. ;; assuming we are in control window, calculate length of the first line in
  478. ;; help message
  479. (defun ediff-help-message-line-length ()
  480.   (save-excursion
  481.     (goto-char (point-min))
  482.     (if ediff-prefer-long-help-message
  483.     (next-line 1))
  484.     (end-of-line)
  485.     (current-column)))
  486.     
  487.     
  488. (defun ediff-indent-help-message ()
  489.   (let* ((shift (/ (max 0 (- (window-width (selected-window))
  490.                  (ediff-help-message-line-length)))
  491.            2))
  492.      (str (make-string shift ?\ )))
  493.     (save-excursion
  494.       (goto-char (point-min))
  495.       (while (< (point) (point-max))
  496.     (insert str)
  497.     (beginning-of-line)
  498.     (forward-line 1)))))
  499.       
  500.  
  501. (defun ediff-set-help-message ()
  502.   (setq ediff-long-help-message
  503.     (cond ((and ediff-long-help-message-custom
  504.             (or (symbolp ediff-long-help-message-custom)
  505.             (consp ediff-long-help-message-custom)))
  506.            (funcall ediff-long-help-message-custom))
  507.           (ediff-word-mode 
  508.            (concat ediff-long-help-message-head
  509.                ediff-long-help-message-word-mode
  510.                ediff-long-help-message-tail))
  511.           (ediff-narrow-job
  512.            (concat ediff-long-help-message-head
  513.                ediff-long-help-message-narrow2
  514.                ediff-long-help-message-tail))
  515.           (ediff-merge-job 
  516.            (concat ediff-long-help-message-head
  517.                ediff-long-help-message-merge
  518.                ediff-long-help-message-tail))
  519.           (ediff-diff3-job
  520.            (concat ediff-long-help-message-head
  521.                ediff-long-help-message-compare3
  522.                ediff-long-help-message-tail))
  523.           (t 
  524.            (concat ediff-long-help-message-head
  525.                ediff-long-help-message-compare2
  526.                ediff-long-help-message-tail))))
  527.   (setq ediff-brief-help-message 
  528.     (cond ((and ediff-brief-help-message-custom
  529.             (or (symbolp ediff-brief-help-message-custom)
  530.             (consp ediff-brief-help-message-custom)))
  531.            (funcall ediff-brief-help-message-custom))
  532.           ((stringp ediff-brief-help-message-custom)
  533.            ediff-brief-help-message-custom)
  534.           ((ediff-multiframe-setup-p) ediff-brief-message-string)
  535.           (t ; long brief msg, not multiframe --- put in the middle
  536.            ediff-brief-message-string)
  537.           ))
  538.   (setq ediff-help-message (if ediff-prefer-long-help-message
  539.                    ediff-long-help-message
  540.                  ediff-brief-help-message))
  541.   (run-hooks 'ediff-display-help-hooks)
  542.   )
  543.  
  544.  
  545.  
  546.  
  547. ;;; Commands for working with Ediff
  548.      
  549. (defun ediff-update-diffs ()
  550.   "Recompute difference regions in buffers A, B, and C.
  551. Buffers are not synchronized with their respective files, so changes done
  552. to these buffers are not saved at this point---the user can do this later,
  553. if necessary."
  554.   (interactive)
  555.   (if (and (ediff-buffer-live-p ediff-ancestor-buffer)
  556.        (not (y-or-n-p "Recompute differences during merge, really? ")))
  557.       (error "God forbid!"))
  558.       
  559.   (let ((point-A (ediff-eval-in-buffer ediff-buffer-A (point)))
  560.     ;;(point-B (ediff-eval-in-buffer ediff-buffer-B (point)))
  561.     (tmp-buffer (get-buffer-create ediff-tmp-buffer))
  562.     (buf-A-file-name
  563.      (file-name-nondirectory (or (buffer-file-name ediff-buffer-A)
  564.                      (buffer-name ediff-buffer-A)
  565.                      )))
  566.     (buf-B-file-name
  567.      (file-name-nondirectory (or (buffer-file-name ediff-buffer-B)
  568.                      (buffer-name ediff-buffer-B)
  569.                      )))
  570.     (buf-C-file-name
  571.      (file-name-nondirectory (or (buffer-file-name ediff-buffer-C)
  572.                      ;; if (null ediff-buffer-C), there is
  573.                      ;; no danger, since we later check if
  574.                      ;; ediff-buffer-C is alive
  575.                      (buffer-name ediff-buffer-C)
  576.                      )))
  577.     (overl-A (ediff-get-value-according-to-buffer-type
  578.           'A ediff-narrow-bounds))
  579.     (overl-B (ediff-get-value-according-to-buffer-type
  580.           'B ediff-narrow-bounds))
  581.     (overl-C (ediff-get-value-according-to-buffer-type
  582.           'C ediff-narrow-bounds))
  583.     beg-A end-A beg-B end-B beg-C end-C
  584.     file-A file-B file-C)
  585.     (ediff-unselect-and-select-difference -1)
  586.     
  587.     (setq beg-A (ediff-overlay-start overl-A)
  588.       beg-B (ediff-overlay-start overl-B)
  589.       beg-C (ediff-overlay-start overl-C)
  590.       end-A (ediff-overlay-end overl-A)
  591.       end-B (ediff-overlay-end overl-B)
  592.       end-C (ediff-overlay-end overl-C))
  593.       
  594.     (if ediff-word-mode
  595.     (progn
  596.       (ediff-wordify beg-A end-A ediff-buffer-A tmp-buffer)
  597.       (setq file-A (ediff-make-temp-file tmp-buffer "regA"))
  598.       (ediff-wordify beg-B end-B ediff-buffer-B tmp-buffer)
  599.       (setq file-B (ediff-make-temp-file tmp-buffer "regB"))
  600.       (if ediff-3way-job
  601.           (progn
  602.         (ediff-wordify beg-C end-C ediff-buffer-C tmp-buffer)
  603.         (setq file-C (ediff-make-temp-file tmp-buffer "regC"))))
  604.       )
  605.       ;; not word-mode
  606.       (setq file-A (ediff-make-temp-file ediff-buffer-A buf-A-file-name))
  607.       (setq file-B (ediff-make-temp-file ediff-buffer-B buf-B-file-name))
  608.       (if ediff-3way-job
  609.       (setq file-C (ediff-make-temp-file ediff-buffer-C buf-C-file-name)))
  610.       )
  611.     
  612.     (ediff-clear-diff-vector 'ediff-difference-vector-A 'fine-diffs-also)
  613.     (ediff-clear-diff-vector 'ediff-difference-vector-B 'fine-diffs-also)
  614.     (ediff-clear-diff-vector 'ediff-difference-vector-C 'fine-diffs-also)
  615.     (ediff-clear-diff-vector
  616.      'ediff-difference-vector-Ancestor 'fine-diffs-also)
  617.     ;; let them garbage collect. we can't use the ancestor after recomputing
  618.     ;; the diffs.
  619.     (setq ediff-difference-vector-Ancestor nil
  620.       ediff-ancestor-buffer nil
  621.       ediff-state-of-merge nil)
  622.  
  623.     (setq ediff-killed-diffs-alist nil) ; invalidate saved killed diff regions
  624.     
  625.     ;; In case of merge job, fool it into thinking that it is just doing
  626.     ;; comparison
  627.     (let ((ediff-setup-diff-regions-function ediff-setup-diff-regions-function)
  628.       (ediff-3way-comparison-job ediff-3way-comparison-job)
  629.       (ediff-merge-job ediff-merge-job)
  630.       (ediff-merge-with-ancestor-job ediff-merge-with-ancestor-job)
  631.       (ediff-job-name ediff-job-name))
  632.       (if ediff-merge-job
  633.       (setq ediff-setup-diff-regions-function 'ediff-setup-diff-regions3
  634.         ediff-3way-comparison-job t
  635.         ediff-merge-job nil
  636.         ediff-merge-with-ancestor-job nil
  637.         ediff-job-name 'ediff-files3))
  638.       (funcall ediff-setup-diff-regions-function file-A file-B file-C))
  639.         
  640.     (setq ediff-number-of-differences (length ediff-difference-vector-A))
  641.     (delete-file file-A)
  642.     (delete-file file-B)
  643.     (if file-C
  644.     (delete-file file-C))
  645.     
  646.     (if ediff-3way-job
  647.     (ediff-set-state-of-all-diffs-in-all-buffers ediff-control-buffer))
  648.     
  649.     (ediff-jump-to-difference (ediff-diff-at-point 'A point-A))
  650.     (message "")
  651.     ))
  652.     
  653. ;; Not bound to any key---to dangerous. A user can do it if necessary.
  654. (defun ediff-revert-buffers-then-recompute-diffs (noconfirm)
  655.   "Revert buffers A, B and C. Then rerun Ediff on file A and file B."
  656.   (interactive "P")
  657.   (let ((bufA ediff-buffer-A)
  658.     (bufB ediff-buffer-B)
  659.     (bufC ediff-buffer-C)
  660.     (ctl-buf ediff-control-buffer)
  661.     (keep-variants ediff-keep-variants)
  662.     (ancestor-buf ediff-ancestor-buffer)
  663.     (ancestor-job ediff-merge-with-ancestor-job)
  664.     (merge ediff-merge-job)
  665.     (comparison ediff-3way-comparison-job))
  666.     (ediff-eval-in-buffer bufA
  667.       (revert-buffer t noconfirm))
  668.     (ediff-eval-in-buffer bufB
  669.       (revert-buffer t noconfirm))
  670.     ;; this should only be executed in a 3way comparison, not in merge
  671.     (if comparison
  672.     (ediff-eval-in-buffer bufC
  673.       (revert-buffer t noconfirm)))
  674.     (if merge
  675.     (progn
  676.       (set-buffer ctl-buf)
  677.       ;; the argument says whether to reverse the meaning of
  678.       ;; ediff-keep-variants, i.e., ediff-really-quit runs here with
  679.       ;; variants kept.
  680.       (ediff-really-quit (not keep-variants))
  681.       (kill-buffer bufC)
  682.       (if ancestor-job
  683.           (ediff-merge-buffers-with-ancestor bufA bufB ancestor-buf)
  684.         (ediff-merge-buffers bufA bufB)))
  685.       (ediff-update-diffs))))
  686.  
  687.  
  688. ;; optional NO-REHIGHLIGHT says to not rehighlight buffers 
  689. (defun ediff-recenter (&optional no-rehighlight)
  690.   "Bring the highlighted region of all buffers being compared into view.
  691. Reestablish the default three-window display."
  692.   (interactive)
  693.   
  694.   ;; force all minibuffer to display ediff's messages.
  695.   ;; when xemacs implements minibufferless frames, this won't be necessary
  696.   (if (and ediff-xemacs-p ediff-synchronize-minibuffers)
  697.       (setq synchronize-minibuffers t))
  698.   
  699.   (setq ediff-disturbed-overlays nil) ; clear after use
  700.   (let (buffer-read-only)
  701.     (if (and (ediff-buffer-live-p ediff-buffer-A)
  702.          (ediff-buffer-live-p ediff-buffer-B)
  703.          (or (not ediff-3way-job)
  704.          (ediff-buffer-live-p ediff-buffer-C)))
  705.     (ediff-setup-windows
  706.      ediff-buffer-A ediff-buffer-B ediff-buffer-C ediff-control-buffer)
  707.       (or (eq this-command 'ediff-quit)
  708.       (message
  709.        "You've killed an essential Ediff buffer---Please quit Ediff"
  710.        (beep 1)))
  711.       ))
  712.       
  713.   ;; set visibility range appropriate to this invocation of Ediff.
  714.   (ediff-visible-region)
  715.   ;; raise
  716.   (if (and (ediff-window-display-p)
  717.        (symbolp this-command)
  718.        (symbolp last-command)
  719.        ;; Either one of the display-changing commands
  720.        (or (memq this-command
  721.              '(ediff-recenter
  722.                ediff-dir-action ediff-registry-action
  723.                ediff-patch-action
  724.                ediff-toggle-wide-display ediff-toggle-multiframe))
  725.            ;; Or one of the movement cmds and prev cmd was an Ediff cmd
  726.            ;; This avoids rasing frames unnecessarily.
  727.            (and (memq this-command
  728.               '(ediff-next-difference
  729.                 ediff-previous-difference
  730.                 ediff-jump-to-difference
  731.                 ediff-jump-to-difference-at-point))
  732.             (not (string-match "^ediff-" (symbol-name last-command)))
  733.             )))
  734.       (progn
  735.     (if (window-live-p ediff-window-A)
  736.         (raise-frame (window-frame ediff-window-A)))
  737.     (if (window-live-p ediff-window-B)
  738.         (raise-frame (window-frame ediff-window-B)))
  739.     (if (window-live-p ediff-window-C)
  740.         (raise-frame (window-frame ediff-window-C)))))
  741.   (if (and (ediff-window-display-p)
  742.        (frame-live-p ediff-control-frame)
  743.        (not ediff-prefer-long-help-message)
  744.        (not (ediff-frame-iconified-p ediff-control-frame)))
  745.       (raise-frame ediff-control-frame))
  746.   
  747.   ;; Redisplay whatever buffers are showing, if there is a selected difference
  748.   (let* ((control-frame ediff-control-frame)
  749.      (control-buf ediff-control-buffer))
  750.     (if (and (ediff-buffer-live-p ediff-buffer-A)
  751.          (ediff-buffer-live-p ediff-buffer-B)
  752.          (or (not ediff-3way-job)
  753.          (ediff-buffer-live-p ediff-buffer-C))
  754.          )
  755.     (progn
  756.       (or no-rehighlight
  757.           (ediff-select-difference ediff-current-difference))
  758.         
  759.       (ediff-recenter-one-window 'A)
  760.       (ediff-recenter-one-window 'B)
  761.       (if ediff-3way-job
  762.           (ediff-recenter-one-window 'C))
  763.  
  764.       (ediff-eval-in-buffer control-buf
  765.         (ediff-recenter-ancestor) ; it checks if ancestor is alive
  766.         
  767.         (if (and (ediff-multiframe-setup-p)
  768.              (not ediff-prefer-long-help-message)
  769.              (not (ediff-frame-iconified-p ediff-control-frame)))
  770.         (ediff-reset-mouse control-frame)))
  771.       ))
  772.     (ediff-eval-in-buffer control-buf
  773.       (ediff-refresh-mode-lines))
  774.     ))
  775.   
  776. ;; this function returns to the window it was called from
  777. ;; (which was the control window)
  778. (defun ediff-recenter-one-window (buf-type)
  779.   (if (ediff-valid-difference-p)
  780.       ;; context must be saved before switching to windows A/B/C
  781.       (let* ((ctl-wind (selected-window))
  782.          (shift (ediff-overlay-start
  783.              (ediff-get-value-according-to-buffer-type 
  784.               buf-type ediff-narrow-bounds)))
  785.          (job-name ediff-job-name)
  786.          (control-buf ediff-control-buffer)
  787.          (window-name (intern (format "ediff-window-%S" buf-type)))
  788.          (window (if (window-live-p (symbol-value window-name))
  789.              (symbol-value window-name))))
  790.     
  791.     (if (and window ediff-windows-job)
  792.         (set-window-start window shift))
  793.     (if window
  794.         (progn
  795.           (select-window window)
  796.           (ediff-deactivate-mark)
  797.           (ediff-position-region
  798.            (ediff-get-diff-posn buf-type 'beg nil control-buf)
  799.            (ediff-get-diff-posn buf-type 'end nil control-buf)
  800.            (ediff-get-diff-posn buf-type 'beg nil control-buf)
  801.            job-name
  802.            )))
  803.     (select-window ctl-wind)
  804.     )))
  805.  
  806. (defun ediff-recenter-ancestor ()
  807.   ;; do half-hearted job by recentering the ancestor buffer, if it is alive and
  808.   ;; visible.
  809.   (if (and (ediff-buffer-live-p ediff-ancestor-buffer)
  810.        (ediff-valid-difference-p))
  811.       (let ((window (ediff-get-visible-buffer-window ediff-ancestor-buffer))
  812.         (ctl-wind (selected-window))
  813.         (job-name ediff-job-name)
  814.         (ctl-buf ediff-control-buffer))
  815.     (ediff-eval-in-buffer ediff-ancestor-buffer
  816.       (goto-char (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf))
  817.       (if window
  818.           (progn
  819.         (select-window window)
  820.         (ediff-position-region
  821.          (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf)
  822.          (ediff-get-diff-posn 'Ancestor 'end nil ctl-buf)
  823.          (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf)
  824.          job-name))))
  825.     (select-window ctl-wind)
  826.     )))
  827.  
  828.     
  829. ;; This will have to be refined for 3way jobs
  830. (defun ediff-toggle-split ()
  831.   "Toggle vertical/horizontal window split. 
  832. Does nothing if file-A and file-B are in different frames."
  833.   (interactive)
  834.   (let* ((wind-A (if (window-live-p ediff-window-A) ediff-window-A))
  835.      (wind-B (if (window-live-p ediff-window-B) ediff-window-B))
  836.      (wind-C (if (window-live-p ediff-window-C) ediff-window-C))
  837.      (frame-A (if wind-A (window-frame wind-A)))
  838.      (frame-B (if wind-B (window-frame wind-B)))
  839.      (frame-C (if wind-C (window-frame wind-C))))
  840.     (if (or (eq frame-A frame-B)
  841.         (not (frame-live-p frame-A))
  842.         (not (frame-live-p frame-B))
  843.         (if ediff-3way-comparison-job
  844.         (or (not (frame-live-p frame-C))
  845.             (eq frame-A frame-C) (eq frame-B frame-C))))
  846.     (setq ediff-split-window-function
  847.           (if (eq ediff-split-window-function 'split-window-vertically)
  848.           'split-window-horizontally
  849.         'split-window-vertically))
  850.       (message "Buffers being compared are in different frames"))
  851.     (ediff-recenter 'no-rehighlight)))
  852.   
  853. (defun ediff-toggle-hilit ()
  854.   "Switch between highlighting using ASCII flags and highlighting using faces.
  855. On a dumb terminal, switches between ASCII highlighting and no highlighting." 
  856.   (interactive)
  857.   (if (not (ediff-window-display-p))
  858.       (if (eq ediff-highlighting-style 'ascii)
  859.       (progn
  860.         (message "ASCII highlighting flags removed")
  861.         (ediff-unselect-and-select-difference ediff-current-difference
  862.                           'unselect-only)
  863.         (setq ediff-highlighting-style 'off))
  864.     (ediff-unselect-and-select-difference ediff-current-difference
  865.                           'select-only))
  866.     (ediff-unselect-and-select-difference ediff-current-difference
  867.                       'unselect-only)
  868.     ;; cycle through highlighting
  869.     (cond ((and ediff-use-faces ediff-highlight-all-diffs)
  870.        (message "Unhighlighting unselected difference regions")
  871.        (setq ediff-highlight-all-diffs nil))
  872.       (ediff-use-faces
  873.        (message "Highlighting with ASCII flags")
  874.        (setq ediff-use-faces nil))
  875.       (t
  876.        (message "Re-highlighting all difference regions")
  877.        (setq ediff-use-faces t
  878.          ediff-highlight-all-diffs t)))
  879.          
  880.     (if (and ediff-use-faces ediff-highlight-all-diffs)
  881.     (ediff-color-background-regions)
  882.       (ediff-color-background-regions 'unhighlight))
  883.     
  884.     (ediff-unselect-and-select-difference
  885.      ediff-current-difference 'select-only))
  886.   )
  887.   
  888. (defun ediff-toggle-autorefine ()
  889.   "Toggle auto-refine mode."
  890.   (interactive)
  891.   (if ediff-word-mode
  892.       (error "No fine differences in this mode"))
  893.   (cond ((eq ediff-auto-refine 'nix)
  894.      (setq ediff-auto-refine 'on)
  895.      (ediff-make-fine-diffs ediff-current-difference 'noforce)
  896.      (message "Auto-refining is ON"))
  897.     ((eq ediff-auto-refine 'on)
  898.      (message "Auto-refining is OFF")
  899.      (setq ediff-auto-refine 'off))
  900.     (t ;; nix 'em
  901.      (ediff-set-fine-diff-properties ediff-current-difference 'default)
  902.      (message "Refinements are HIDDEN")
  903.      (setq ediff-auto-refine 'nix))
  904.     ))
  905.  
  906. (defun ediff-show-ancestor ()
  907.   "Show the ancestor buffer in a suitable window."
  908.   (interactive)
  909.   (ediff-recenter)
  910.   (or (ediff-buffer-live-p ediff-ancestor-buffer)
  911.       (if ediff-merge-with-ancestor-job
  912.       (error "Lost connection to ancestor buffer...sorry")
  913.     (error "Not merging with ancestor")))
  914.   (let (wind)
  915.     (cond ((setq wind (ediff-get-visible-buffer-window ediff-ancestor-buffer))
  916.        (raise-frame (window-frame wind)))
  917.       (t (set-window-buffer ediff-window-C ediff-ancestor-buffer)))))
  918.     
  919. (defun ediff-make-or-kill-fine-diffs (arg)
  920.   "Compute fine diffs. With negative prefix arg, kill fine diffs.
  921. In both cases, operates on the currrent difference region." 
  922.   (interactive "P")
  923.   (cond ((eq arg '-)
  924.      (ediff-clear-fine-differences ediff-current-difference))
  925.     ((and (numberp arg) (< arg 0))
  926.      (ediff-clear-fine-differences ediff-current-difference))
  927.     (t (ediff-make-fine-diffs))))
  928.      
  929.   
  930. (defun ediff-toggle-help ()
  931.   "Toggle short/long help message."
  932.   (interactive)
  933.   (let (buffer-read-only)
  934.     (erase-buffer)
  935.     (setq ediff-prefer-long-help-message (not ediff-prefer-long-help-message))
  936.     (ediff-set-help-message))
  937.   ;; remember the icon status of the control frame when the user requested
  938.   ;; full control message
  939.   (if (and ediff-prefer-long-help-message (ediff-multiframe-setup-p))
  940.       (setq ediff-prefer-iconified-control-frame
  941.         (ediff-frame-iconified-p ediff-control-frame)))
  942.         
  943.   (setq ediff-window-config-saved "") ; force redisplay
  944.   (ediff-recenter 'no-rehighlight))
  945.   
  946.   
  947. ;; If BUF, this is the buffer to toggle, not current buffer.
  948. (defun ediff-toggle-read-only (&optional buf)
  949.   "Toggle read-only in current buffer.
  950. If buffer is under version control and locked, check it out first.
  951. If optional argument BUF is specified, toggle read-only in that buffer instead
  952. of the current buffer."
  953.   (interactive)
  954.   (let ((ctl-buf (if (null buf) (current-buffer))))
  955.     (or buf (ediff-recenter))
  956.     (or buf
  957.     (setq buf
  958.           (ediff-get-buffer (ediff-char-to-buftype last-command-char))))
  959.           
  960.     (ediff-eval-in-buffer buf     ; eval in buf A/B/C
  961.       (let* ((file (buffer-file-name buf))
  962.          (file-writable (and file
  963.                  (file-exists-p file)
  964.                  (file-writable-p file)))
  965.          (toggle-ro-cmd (cond (ediff-toggle-read-only-function)
  966.                   ((ediff-file-checked-out-p file)
  967.                    'toggle-read-only)
  968.                   (file-writable 'toggle-read-only)
  969.                   (t (key-binding "\C-x\C-q")))))
  970.     ;; If the file is checked in, make sure we don't make buffer modifiable
  971.     ;; without warning the user. The user can fool our checks by making the
  972.     ;; buffer non-RO without checking the file out. We regard this as a
  973.     ;; user problem.
  974.     (if (and (ediff-file-checked-in-p file)
  975.          ;; If ctl-buf is null, this means we called this
  976.          ;; non-interactively, in which case don't ask questions
  977.          ctl-buf)
  978.         (cond ((not buffer-read-only)
  979.            (setq toggle-ro-cmd 'toggle-read-only))
  980.           ((and (or (beep 1) t) ; always beep
  981.             (y-or-n-p
  982.              (format
  983.               "File %s is under version control. Check it out? "
  984.               (ediff-abbreviate-file-name file))))
  985.            ;; if we checked the file out, we should also change the
  986.            ;; original state of buffer-read-only to nil.  If we don't
  987.            ;; do this, the mode line will show %%, since the file was
  988.            ;; RO before ediff started, so the user will think the file
  989.            ;; is checked in.
  990.            (ediff-eval-in-buffer ctl-buf
  991.              (ediff-change-saved-variable
  992.               'buffer-read-only nil
  993.               (ediff-char-to-buftype last-command-char))))
  994.           (t
  995.            (setq toggle-ro-cmd 'toggle-read-only)
  996.            (beep 1) (beep 1)
  997.            (message
  998.             "Boy, this is risky! Better don't change this file...")
  999.            (sit-for 3)))) ; let the user see the warning
  1000.     (if (and toggle-ro-cmd 
  1001.          (string-match "toggle-read-only" (symbol-name toggle-ro-cmd)))
  1002.         (save-excursion
  1003.           (save-window-excursion
  1004.         (command-execute toggle-ro-cmd)))
  1005.       (error "Don't know how to toggle read-only in buffer %S" buf))
  1006.     
  1007.     ;; Check if we made the current buffer updatable, but its file is RO.
  1008.     ;; Signal a warning in this case.
  1009.     (if (and file (not buffer-read-only)
  1010.          (eq this-command 'ediff-toggle-read-only)
  1011.          (file-exists-p file)
  1012.          (not (file-writable-p file)))
  1013.         (message "Warning: file %s is read-only"
  1014.              (ediff-abbreviate-file-name file) (beep 1)))
  1015.     ))))
  1016.   
  1017.  
  1018. ;; This is a simple-minded check for whether a file is under version control
  1019. ;; and is checked out.
  1020. ;; If file,v exists but file doesn't, this file is considered to be not checked
  1021. ;; in and not checked out for the purpose of patching (since patch won't be
  1022. ;; able to read such a file anyway).
  1023. ;; FILE is a string representing file name
  1024. (defsubst ediff-file-checked-out-p (file)
  1025.   (and (stringp file)
  1026.        (file-exists-p file)
  1027.        (file-writable-p file)
  1028.        (file-exists-p (concat file ",v"))))
  1029. (defsubst ediff-file-checked-in-p (file)
  1030.   (and (stringp file)
  1031.        (file-exists-p file)
  1032.        (not (file-writable-p file))
  1033.        (file-exists-p (concat file ",v"))))
  1034.       
  1035. (defun ediff-swap-buffers ()
  1036.   "Rotate the display of buffers A, B, and C."
  1037.   (interactive)
  1038.   (if (and (window-live-p ediff-window-A) (window-live-p ediff-window-B))
  1039.       (let ((buf ediff-buffer-A)
  1040.         (values ediff-buffer-values-orig-A)
  1041.         (diff-vec ediff-difference-vector-A)
  1042.         (hide-regexp ediff-regexp-hide-A)
  1043.         (focus-regexp ediff-regexp-focus-A)
  1044.         (wide-visibility-p (eq ediff-visible-bounds ediff-wide-bounds))
  1045.         (overlay (if (ediff-window-display-p)
  1046.              ediff-current-diff-overlay-A)))
  1047.     (if ediff-3way-comparison-job
  1048.         (progn
  1049.           (set-window-buffer ediff-window-A ediff-buffer-C)
  1050.           (set-window-buffer ediff-window-B ediff-buffer-A)
  1051.           (set-window-buffer ediff-window-C ediff-buffer-B)
  1052.           )
  1053.       (set-window-buffer ediff-window-A ediff-buffer-B)
  1054.       (set-window-buffer ediff-window-B ediff-buffer-A))
  1055.     ;; swap diff buffers
  1056.     (if ediff-3way-comparison-job
  1057.         (setq ediff-buffer-A ediff-buffer-C
  1058.           ediff-buffer-C ediff-buffer-B
  1059.           ediff-buffer-B buf)
  1060.       (setq ediff-buffer-A ediff-buffer-B
  1061.         ediff-buffer-B buf))
  1062.         
  1063.     ;; swap saved buffer characteristics
  1064.     (if ediff-3way-comparison-job
  1065.         (setq ediff-buffer-values-orig-A ediff-buffer-values-orig-C
  1066.           ediff-buffer-values-orig-C ediff-buffer-values-orig-B
  1067.           ediff-buffer-values-orig-B values)
  1068.       (setq ediff-buffer-values-orig-A ediff-buffer-values-orig-B
  1069.         ediff-buffer-values-orig-B values))
  1070.     
  1071.     ;; swap diff vectors
  1072.     (if ediff-3way-comparison-job
  1073.         (setq ediff-difference-vector-A ediff-difference-vector-C
  1074.           ediff-difference-vector-C ediff-difference-vector-B
  1075.           ediff-difference-vector-B diff-vec)
  1076.       (setq ediff-difference-vector-A ediff-difference-vector-B
  1077.         ediff-difference-vector-B diff-vec))
  1078.         
  1079.     ;; swap hide/focus regexp
  1080.     (if ediff-3way-comparison-job
  1081.         (setq ediff-regexp-hide-A ediff-regexp-hide-C
  1082.           ediff-regexp-hide-C ediff-regexp-hide-B
  1083.           ediff-regexp-hide-B hide-regexp
  1084.           ediff-regexp-focus-A ediff-regexp-focus-C
  1085.           ediff-regexp-focus-C ediff-regexp-focus-B
  1086.           ediff-regexp-focus-B focus-regexp)
  1087.       (setq ediff-regexp-hide-A ediff-regexp-hide-B
  1088.         ediff-regexp-hide-B hide-regexp
  1089.         ediff-regexp-focus-A ediff-regexp-focus-B
  1090.         ediff-regexp-focus-B focus-regexp))
  1091.     
  1092.     ;; The following is needed for XEmacs, since there one can't move
  1093.     ;; overlay to another buffer. In Emacs, this swap is redundant.
  1094.     (if (ediff-window-display-p)
  1095.         (if ediff-3way-comparison-job
  1096.         (setq ediff-current-diff-overlay-A ediff-current-diff-overlay-C
  1097.               ediff-current-diff-overlay-C ediff-current-diff-overlay-B
  1098.               ediff-current-diff-overlay-B overlay)
  1099.           (setq ediff-current-diff-overlay-A ediff-current-diff-overlay-B
  1100.             ediff-current-diff-overlay-B overlay)))
  1101.             
  1102.     ;; swap wide bounds
  1103.     (setq ediff-wide-bounds
  1104.           (cond (ediff-3way-comparison-job
  1105.              (list (nth 2 ediff-wide-bounds)
  1106.                (nth 0 ediff-wide-bounds)
  1107.                (nth 1 ediff-wide-bounds)))
  1108.             (ediff-3way-job
  1109.              (list (nth 1 ediff-wide-bounds)
  1110.                (nth 0 ediff-wide-bounds)
  1111.                (nth 2 ediff-wide-bounds)))
  1112.             (t 
  1113.              (list (nth 1 ediff-wide-bounds)
  1114.                (nth 0 ediff-wide-bounds)))))
  1115.     ;; swap narrow bounds
  1116.     (setq ediff-narrow-bounds
  1117.           (cond (ediff-3way-comparison-job
  1118.              (list (nth 2 ediff-narrow-bounds)
  1119.                (nth 0 ediff-narrow-bounds)
  1120.                (nth 1 ediff-narrow-bounds)))
  1121.             (ediff-3way-job
  1122.              (list (nth 1 ediff-narrow-bounds)
  1123.                (nth 0 ediff-narrow-bounds)
  1124.                (nth 2 ediff-narrow-bounds)))
  1125.             (t 
  1126.              (list (nth 1 ediff-narrow-bounds)
  1127.                (nth 0 ediff-narrow-bounds)))))
  1128.     (if wide-visibility-p
  1129.         (setq ediff-visible-bounds ediff-wide-bounds)
  1130.       (setq ediff-visible-bounds ediff-narrow-bounds))
  1131.     ))
  1132.   (if ediff-3way-job
  1133.       (ediff-set-state-of-all-diffs-in-all-buffers ediff-control-buffer))
  1134.   (ediff-recenter 'no-rehighlight)
  1135.   )
  1136.   
  1137.  
  1138. (defun ediff-toggle-wide-display ()
  1139.   "Toggle wide/regular display.
  1140. This is especially useful when comparing buffers side-by-side."
  1141.   (interactive)
  1142.   (or (ediff-window-display-p)
  1143.       (error "%sEmacs is not running as a window application"
  1144.          (if ediff-emacs-p "" "X")))
  1145.   (ediff-recenter 'no-rehighlight) ; make sure buffs are displayed in windows
  1146.   (let ((ctl-buf ediff-control-buffer))
  1147.     (setq ediff-wide-display-p (not ediff-wide-display-p))
  1148.     (if (not ediff-wide-display-p)
  1149.     (ediff-eval-in-buffer ctl-buf
  1150.       (modify-frame-parameters
  1151.        ediff-wide-display-frame ediff-wide-display-orig-parameters)
  1152.       ;;(sit-for (if ediff-xemacs-p 0.4 0))
  1153.       ;; restore control buf, since ctl window may have been deleted
  1154.       ;; during resizing
  1155.       (set-buffer ctl-buf)
  1156.       (setq ediff-wide-display-orig-parameters nil
  1157.         ediff-window-B nil) ; force update of window config
  1158.       (ediff-recenter 'no-rehighlight))
  1159.       (funcall ediff-make-wide-display-function)
  1160.       ;;(sit-for (if ediff-xemacs-p 0.4 0))
  1161.       (ediff-eval-in-buffer ctl-buf
  1162.     (setq ediff-window-B nil) ; force update of window config
  1163.     (ediff-recenter 'no-rehighlight)))))
  1164.     
  1165. (defun ediff-toggle-multiframe ()
  1166.   "Switch from the multiframe display to single-frame display and back.
  1167. This is primarily for debugging, but one can use it for fun, too."
  1168.   (interactive)
  1169.   (or (ediff-window-display-p)
  1170.       (error "%sEmacs is not running as a window application"
  1171.          (if ediff-emacs-p "" "X")))
  1172.   (cond ((eq ediff-window-setup-function 'ediff-setup-windows-multiframe)
  1173.      (setq ediff-window-setup-function 'ediff-setup-windows-plain))
  1174.     ((eq ediff-window-setup-function 'ediff-setup-windows-plain)
  1175.      (setq ediff-window-setup-function 'ediff-setup-windows-multiframe)))
  1176.   (setq ediff-window-B nil)
  1177.   (ediff-recenter 'no-rehighlight))
  1178.            
  1179. ;; Merging
  1180.  
  1181. (defun ediff-toggle-show-clashes-only ()
  1182.   "Toggle the mode where only the regions where both buffers differ with the ancestor are shown."
  1183.   (interactive)
  1184.   (if (not ediff-merge-with-ancestor-job)
  1185.       (error "This command makes sense only when merging with an ancestor"))
  1186.   (setq ediff-show-clashes-only (not ediff-show-clashes-only))
  1187.   (if ediff-show-clashes-only
  1188.       (message "Focus on regions where both buffers differ from the ancestor")
  1189.     (message "Canceling focus on regions where changes clash")))
  1190.            
  1191. ;; Widening/narrowing
  1192.  
  1193. (defun ediff-toggle-narrow-region ()
  1194.   "Toggle narrowing in buffers A, B, and C.
  1195. Used in ediff-windows/regions only."
  1196.   (interactive)
  1197.   (if (eq ediff-buffer-A ediff-buffer-B)
  1198.       (error
  1199.        "Buffers A and B are the same. Can't narrow to two different regions"))
  1200.   (if (eq ediff-visible-bounds ediff-wide-bounds)
  1201.       (setq ediff-visible-bounds ediff-narrow-bounds)
  1202.     (setq ediff-visible-bounds ediff-wide-bounds))
  1203.   (ediff-recenter 'no-rehighlight))
  1204.   
  1205. ;; Narrow bufs A/B/C to ediff-visible-bounds. If this is currently set to
  1206. ;; ediff-wide-bounds, then this actually widens.
  1207. ;; This function does nothing if job-name is not
  1208. ;; ediff-regions-wordwise/linewise or ediff-windows-wordwise/linewise. 
  1209. ;; Does nothing if buffer-A  = buffer-B since we can't narrow
  1210. ;; to two different regions in one buffer.
  1211. (defun ediff-visible-region ()
  1212.   (if (or (eq ediff-buffer-A ediff-buffer-B)
  1213.       (eq ediff-buffer-A ediff-buffer-C)
  1214.       (eq ediff-buffer-C ediff-buffer-B))
  1215.       ()
  1216.     ;; If ediff-*-regions/windows, ediff-visible-bounds is already set
  1217.     ;; Otherwise, always use full range.
  1218.     (if (not ediff-narrow-job)
  1219.     (setq ediff-visible-bounds ediff-wide-bounds))
  1220.     (let ((overl-A (ediff-get-value-according-to-buffer-type
  1221.             'A  ediff-visible-bounds))
  1222.       (overl-B (ediff-get-value-according-to-buffer-type
  1223.             'B  ediff-visible-bounds))
  1224.       (overl-C (ediff-get-value-according-to-buffer-type
  1225.             'C  ediff-visible-bounds))
  1226.       )
  1227.       (ediff-eval-in-buffer ediff-buffer-A
  1228.     (narrow-to-region
  1229.      (ediff-overlay-start overl-A) (ediff-overlay-end overl-A)))
  1230.       (ediff-eval-in-buffer ediff-buffer-B
  1231.     (narrow-to-region
  1232.      (ediff-overlay-start overl-B) (ediff-overlay-end overl-B)))
  1233.       
  1234.       (if ediff-3way-job
  1235.       (ediff-eval-in-buffer ediff-buffer-C
  1236.         (narrow-to-region
  1237.          (ediff-overlay-start overl-C) (ediff-overlay-end overl-C))))
  1238.       )))
  1239.   
  1240.  
  1241. ;; Window scrolling operations
  1242.  
  1243. ;; Performs some operation on the two file windows (if they are showing).
  1244. ;; Traps all errors on the operation in windows A/B/C.
  1245. ;; Usually, errors come from scrolling off the
  1246. ;; beginning or end of the buffer, and this gives error messages.
  1247. (defun ediff-operate-on-windows (operation arg)
  1248.      
  1249.   ;; make sure windows aren't dead
  1250.   (if (not (and (window-live-p ediff-window-A) (window-live-p ediff-window-B)))
  1251.       (ediff-recenter 'no-rehighlight))
  1252.   (if (not (and (ediff-buffer-live-p ediff-buffer-A)
  1253.         (ediff-buffer-live-p ediff-buffer-B)
  1254.         (or (not ediff-3way-job) ediff-buffer-C)
  1255.         ))
  1256.       (error "You've killed an essential Ediff buffer---Please quit Ediff"))
  1257.     
  1258.   (let* ((wind (selected-window))
  1259.      (wind-A ediff-window-A)
  1260.      (wind-B ediff-window-B)
  1261.      (wind-C ediff-window-C)
  1262.      (three-way ediff-3way-job))
  1263.          
  1264.     (select-window wind-A)
  1265.     (condition-case nil
  1266.     (funcall operation arg)
  1267.       (error))
  1268.     (select-window wind-B)
  1269.     (condition-case nil
  1270.     (funcall operation arg)
  1271.       (error))
  1272.     (if three-way
  1273.     (progn
  1274.       (select-window wind-C)
  1275.       (condition-case nil
  1276.           (funcall operation arg)
  1277.         (error))))
  1278.     
  1279.     (select-window wind)))
  1280.  
  1281. (defun ediff-scroll-vertically (&optional arg)
  1282.   "Vertically scroll buffers A, B \(and C if appropriate\).
  1283. With optional argument ARG, scroll ARG lines; otherwise scroll by nearly
  1284. the height of window-A."
  1285.   (interactive "P")
  1286.   
  1287.   ;; make sure windows aren't dead
  1288.   (if (not (and (window-live-p ediff-window-A) (window-live-p ediff-window-B)))
  1289.       (ediff-recenter 'no-rehighlight))
  1290.   (if (not (and (ediff-buffer-live-p ediff-buffer-A)
  1291.         (ediff-buffer-live-p ediff-buffer-B)
  1292.         (or (not ediff-3way-job)
  1293.             (ediff-buffer-live-p ediff-buffer-C))
  1294.         ))
  1295.       (error "You've killed an essential Ediff buffer---Please quit Ediff"))
  1296.       
  1297.   (ediff-operate-on-windows
  1298.    (if (memq last-command-char '(?v ?\C-v))
  1299.        'scroll-up 
  1300.      'scroll-down)
  1301.    ;; calculate argument to scroll-up/down
  1302.    ;; if there is an explicit argument
  1303.    (if (and arg (not (equal arg '-)))
  1304.        ;; use it
  1305.        (prefix-numeric-value arg)
  1306.      ;; if not, see if we can determine a default amount (the window height)
  1307.      (let* (default-amount)
  1308.        (setq default-amount 
  1309.          (- (min (window-height ediff-window-A)
  1310.              (window-height ediff-window-B)
  1311.              (if ediff-3way-job
  1312.              (window-height ediff-window-C)
  1313.                123) ; some large number
  1314.              )
  1315.         1 next-screen-context-lines))
  1316.        ;; window found
  1317.        (if arg
  1318.        ;; C-u as argument means half of default amount
  1319.        (/ default-amount 2)
  1320.      ;; no argument means default amount
  1321.      default-amount)))))
  1322.  
  1323.  
  1324. (defun ediff-scroll-horizontally (&optional arg)
  1325.   "Horizontally scroll buffers A, B \(and C if appropriate\).
  1326. If an argument is given, that is how many columns are scrolled, else nearly
  1327. the width of the A/B/C windows."
  1328.   (interactive "P")
  1329.   
  1330.   ;; make sure windows aren't dead
  1331.   (if (not (and (window-live-p ediff-window-A) (window-live-p ediff-window-B)))
  1332.       (ediff-recenter 'no-rehighlight))
  1333.   (if (not (and (ediff-buffer-live-p ediff-buffer-A)
  1334.         (ediff-buffer-live-p ediff-buffer-B)
  1335.         (or (not ediff-3way-job)
  1336.             (ediff-buffer-live-p ediff-buffer-C))
  1337.         ))
  1338.       (error "You've killed an essential Ediff buffer---Please quit Ediff"))
  1339.     
  1340.   (ediff-operate-on-windows
  1341.    (if (= last-command-char ?<)
  1342.        'scroll-left
  1343.      'scroll-right)
  1344.    ;; calculate argument to scroll-left/right
  1345.    ;; if there is an explicit argument
  1346.    (if (and arg (not (equal arg '-)))
  1347.        ;; use it
  1348.        (prefix-numeric-value arg)
  1349.      ;; if not, see if we can determine a default amount
  1350.      ;; (half the window width)
  1351.      (if (null ediff-control-window)
  1352.      ;; no control window, use nil
  1353.      nil
  1354.        (let ((default-amount
  1355.            (- (/ (min (window-width ediff-window-A)
  1356.               (window-width ediff-window-B)
  1357.               (if ediff-3way-comparison-job
  1358.                   (window-width ediff-window-C)
  1359.                 500) ; some large number
  1360.               )
  1361.              2)
  1362.           3)))
  1363.      ;; window found
  1364.      (if arg
  1365.          ;; C-u as argument means half of default amount
  1366.          (/ default-amount 2)
  1367.        ;; no argument means default amount
  1368.        default-amount))))))
  1369.  
  1370.  
  1371. ;;BEG, END show the region to be positioned.
  1372. ;;JOB-NAME holds ediff-job-name. Ediff-windows job positions regions
  1373. ;;differently. 
  1374. (defun ediff-position-region (beg end pos job-name)
  1375.   (if (> end (point-max))
  1376.       (setq end (point-max)))
  1377.   (if ediff-windows-job
  1378.       (if (pos-visible-in-window-p end)
  1379.       () ; do nothing, wind is already positioned
  1380.     ;; at this point, windows are positioned at the beginning of the
  1381.     ;; file regions (not diff-regions)  being compared.
  1382.     (save-excursion
  1383.       (move-to-window-line (- (window-height) 2))
  1384.       (let ((amount (+ 2 (count-lines (point) end))))
  1385.         (scroll-up amount))))
  1386.     (set-window-start (selected-window) beg)
  1387.     (if (pos-visible-in-window-p end)
  1388.     ;; Determine the number of lines that the region occupies
  1389.     (let ((lines 0)
  1390.           (prev-point 0))
  1391.       (while ( and (> end (progn
  1392.                 (move-to-window-line lines)
  1393.                 (point)))
  1394.                ;; `end' may be beyond the window bottom, so check
  1395.                ;; that we are making progres
  1396.                (< prev-point (point)))
  1397.         (setq prev-point (point))
  1398.         (setq lines (1+ lines)))
  1399.       ;; And position the beginning on the right line
  1400.       (goto-char beg)
  1401.       (recenter (/ (1+ (max (- (1- (window-height (selected-window)))
  1402.                    lines)
  1403.                 1)
  1404.                )
  1405.                2))))
  1406.     (goto-char pos)
  1407.     ))
  1408.  
  1409.  
  1410. (defun ediff-next-difference (&optional arg)
  1411.   "Advance to the next difference. 
  1412. With a prefix argument, go back that many differences."
  1413.   (interactive "P")
  1414.   (if (< ediff-current-difference ediff-number-of-differences)
  1415.       (let ((n (min ediff-number-of-differences
  1416.             (+ ediff-current-difference (if arg arg 1))))
  1417.         regexp-skip)
  1418.         
  1419.     (or (>= n ediff-number-of-differences)
  1420.         (setq regexp-skip (funcall ediff-skip-diff-region-function n))
  1421.         (ediff-install-fine-diff-if-necessary n))
  1422.     (while (and (< n ediff-number-of-differences)
  1423.             (or
  1424.              ;; regexp skip
  1425.              regexp-skip
  1426.              ;; skip clashes, if necessary
  1427.              (and ediff-show-clashes-only
  1428.               (string-match "prefer"
  1429.                     (or (ediff-get-state-of-merge n) "")))
  1430.              ;; skip difference regions that differ in white space
  1431.              (and ediff-ignore-similar-regions
  1432.               (ediff-no-fine-diffs-p n))))
  1433.       (setq n (1+ n))
  1434.       (if (= 0 (mod n 20))
  1435.           (message "Skipped over region %d and counting ..."  n))
  1436.       (or (>= n ediff-number-of-differences)
  1437.           (setq regexp-skip (funcall ediff-skip-diff-region-function n))
  1438.           (ediff-install-fine-diff-if-necessary n))
  1439.       )
  1440.     (message "")
  1441.     (ediff-unselect-and-select-difference n)
  1442.     ) ; let
  1443.     (ediff-visible-region)
  1444.     (error "At end of the difference list")))
  1445.  
  1446. (defun ediff-previous-difference (&optional arg)
  1447.   "Go to the previous difference. 
  1448. With a prefix argument, go back that many differences."
  1449.   (interactive "P")
  1450.   (if (> ediff-current-difference -1)
  1451.       (let ((n (max -1 (- ediff-current-difference (if arg arg 1))))
  1452.         regexp-skip)
  1453.         
  1454.     (or (< n 0)
  1455.         (setq regexp-skip (funcall ediff-skip-diff-region-function n))
  1456.         (ediff-install-fine-diff-if-necessary n))
  1457.     (while (and (> n -1)
  1458.             (or
  1459.              ;; regexp skip
  1460.              regexp-skip
  1461.              ;; skip clashes, if necessary
  1462.              (and ediff-show-clashes-only
  1463.               (string-match "prefer"
  1464.                     (or (ediff-get-state-of-merge n) "")))
  1465.              ;; skip difference regions that differ in white space
  1466.              (and ediff-ignore-similar-regions
  1467.               (ediff-no-fine-diffs-p n))))
  1468.       (if (= 0 (mod (1+ n) 20))
  1469.           (message "Skipped over region %d and counting ..."  (1+ n)))
  1470.       (setq n (1- n))
  1471.       (or (< n 0)
  1472.           (setq regexp-skip (funcall ediff-skip-diff-region-function n))
  1473.           (ediff-install-fine-diff-if-necessary n))
  1474.       )
  1475.     (message "")
  1476.     (ediff-unselect-and-select-difference n)
  1477.     ) ; let
  1478.     (ediff-visible-region)
  1479.     (error "At beginning of the difference list")))
  1480.  
  1481. (defun ediff-jump-to-difference (difference-number)
  1482.   "Go to the difference specified as a prefix argument."
  1483.   (interactive "p")
  1484.   (setq difference-number (1- difference-number))
  1485.   (if (and (>= difference-number -1)
  1486.        (< difference-number (1+ ediff-number-of-differences)))
  1487.       (ediff-unselect-and-select-difference difference-number)
  1488.     (error "Bad difference number, %d" difference-number)))
  1489.       
  1490. (defun ediff-jump-to-difference-at-point ()
  1491.   "Go to difference closest to the point in buffer A, B, or C.
  1492. The type of buffer depends on last command character \(a, b, or c\) that
  1493. invoked this command."
  1494.   (interactive)
  1495.   (let ((buf-type (ediff-char-to-buftype last-command-char)))
  1496.     (ediff-jump-to-difference (ediff-diff-at-point buf-type))))
  1497.     
  1498.       
  1499. ;; find region most related to the current point position (or POS, if given)
  1500. (defun ediff-diff-at-point (buf-type &optional pos)
  1501.   (let ((buffer (ediff-get-buffer buf-type))
  1502.     (ctl-buffer ediff-control-buffer)
  1503.     (max-dif-num (1- ediff-number-of-differences))
  1504.     (diff-no -1)
  1505.     (prev-beg 0)
  1506.     (prev-end 0)
  1507.     (beg 0)
  1508.     (end 0))
  1509.     
  1510.     (ediff-eval-in-buffer buffer
  1511.       (setq pos (or pos (point)))
  1512.       (while (and (or (< pos prev-beg) (> pos beg))
  1513.           (< diff-no max-dif-num))
  1514.     (setq diff-no (1+ diff-no))
  1515.     (setq prev-beg beg
  1516.           prev-end end)
  1517.     (setq beg (ediff-get-diff-posn buf-type 'beg diff-no ctl-buffer)
  1518.           end (ediff-get-diff-posn buf-type 'end diff-no ctl-buffer))
  1519.     )
  1520.       
  1521.      (if (< (abs (- pos prev-end))
  1522.         (abs (- pos beg)))
  1523.      diff-no
  1524.        (1+ diff-no)) ; jump-to-diff works with diff nums higher by 1
  1525.      )))
  1526.  
  1527.  
  1528. ;;; Copying diffs.
  1529.  
  1530. (defun ediff-diff-to-diff (arg &optional keys)
  1531.   "Copy buffer-X'th diff to buffer Y \(X,Y are A, B, or C\).
  1532. If numerical prefix argument, copy this diff specified in the arg.
  1533. Otherwise, copy the difference given by `ediff-current-difference'.
  1534. This command assumes it is bound to a 2-character key sequence, `ab', `ba',
  1535. `ac', etc., which is used to determine the types of buffers to be used for
  1536. copying difference regions. The first character in the sequence specifies
  1537. the source buffer and the second specifies the target.
  1538.  
  1539. If the second optional argument, a 2-character string, is given, use it to
  1540. determine the source and the target buffers instead of the command keys."
  1541.   (interactive "P")
  1542.   (or keys (setq keys (this-command-keys)))
  1543.   (if arg
  1544.       (ediff-jump-to-difference arg))
  1545.   (let* ((key1 (aref keys 0))
  1546.      (key2 (aref keys 1))
  1547.      (char1 (if (and ediff-xemacs-p (eventp key1)) (event-key key1) key1))
  1548.      (char2 (if (and ediff-xemacs-p (eventp key1)) (event-key key2) key2))
  1549.      ediff-verbose-p)
  1550.     (ediff-copy-diff ediff-current-difference
  1551.              (ediff-char-to-buftype char1)
  1552.              (ediff-char-to-buftype char2))
  1553.     ;; recenter with rehighlighting, but no messages
  1554.     (ediff-recenter)))
  1555.  
  1556.  
  1557. ;; Copy diff N from FROM-BUF-TYPE \(given as A, B or C\) to TO-BUF-TYPE.
  1558. ;; If optional DO-NOT-SAVE is non-nil, do not save the old value of the
  1559. ;; target diff. This is used in merging, when constructing the merged
  1560. ;; version.
  1561. (defun ediff-copy-diff (n from-buf-type to-buf-type
  1562.               &optional batch-invocation reg-to-copy)
  1563.   (let* ((to-buf (ediff-get-buffer to-buf-type))
  1564.      ;;(from-buf (if (not reg-to-copy) (ediff-get-buffer from-buf-type)))
  1565.      (ctrl-buf ediff-control-buffer)
  1566.      (saved-p t)
  1567.      (three-way ediff-3way-job)
  1568.      messg
  1569.      ediff-verbose-p
  1570.      reg-to-delete reg-to-delete-beg reg-to-delete-end)
  1571.     
  1572.     (setq reg-to-delete-beg
  1573.       (ediff-get-diff-posn to-buf-type 'beg n ctrl-buf))
  1574.     (setq reg-to-delete-end
  1575.       (ediff-get-diff-posn to-buf-type 'end n ctrl-buf))
  1576.       
  1577.     (if reg-to-copy
  1578.     (setq from-buf-type nil)
  1579.       (setq reg-to-copy (ediff-get-region-contents n from-buf-type ctrl-buf)))
  1580.     
  1581.     (setq reg-to-delete (ediff-get-region-contents
  1582.              n to-buf-type ctrl-buf
  1583.              reg-to-delete-beg reg-to-delete-end))
  1584.     
  1585.     (setq ediff-disturbed-overlays nil) ; clear before use
  1586.     
  1587.     (if (string= reg-to-delete reg-to-copy)
  1588.     (setq saved-p nil)     ; refuse to copy identical buffers
  1589.       ;; seems ok to copy
  1590.       (if (or batch-invocation (ediff-test-save-region n to-buf-type))
  1591.       (condition-case conds
  1592.           (progn
  1593.         (ediff-eval-in-buffer to-buf
  1594.           ;; to prevent flags from interfering if buffer is writable
  1595.           (let ((inhibit-read-only (null buffer-read-only)))
  1596.             ;; these two insert a dummy char to overcome a bug in
  1597.             ;; XEmacs, which sometimes prevents 0-length extents
  1598.             ;; from sensing insertion at its end-points.
  1599.             ;; (need to check if 19.12 still has the bug)
  1600.             (if ediff-xemacs-p
  1601.             (progn
  1602.               (goto-char reg-to-delete-end)
  1603.               (insert-before-markers "@")))
  1604.             
  1605.             (goto-char reg-to-delete-end)
  1606.             (insert-before-markers reg-to-copy)
  1607.             
  1608.             ;; delete the dummy char "@"
  1609.             (if ediff-xemacs-p
  1610.             (delete-char 1))
  1611.             
  1612.             (if ediff-xemacs-p
  1613.             (if (> reg-to-delete-end reg-to-delete-beg)
  1614.                 (kill-region reg-to-delete-beg
  1615.                      reg-to-delete-end))
  1616.               (if (> reg-to-delete-end reg-to-delete-beg)
  1617.               (kill-region reg-to-delete-beg reg-to-delete-end)
  1618.             (ediff-move-disturbed-overlays reg-to-delete-beg)
  1619.             ))
  1620.             ))
  1621.         (or batch-invocation
  1622.             (setq 
  1623.              messg
  1624.              (ediff-save-diff-region n to-buf-type reg-to-delete))))
  1625.         (error (message "ediff-copy-diff: %s %s"
  1626.                 (car conds)
  1627.                 (mapconcat 'prin1-to-string (cdr conds) " "))
  1628.            (beep 1)
  1629.            (sit-for 2) ; let the user see the error msg
  1630.            (setq saved-p nil)
  1631.            )))
  1632.       )
  1633.     
  1634.     ;; adjust state of difference in case 3-way and diff was copied ok
  1635.     (if (and saved-p three-way)
  1636.     (ediff-set-state-of-diff-in-all-buffers n ctrl-buf))
  1637.  
  1638.     (if batch-invocation
  1639.     (ediff-clear-fine-differences n)
  1640.       ;; If diff3 job, we should recompute fine diffs so we clear them
  1641.       ;; before reinserting flags (and thus before ediff-recenter).
  1642.       (if (and saved-p three-way)
  1643.       (ediff-clear-fine-differences n))
  1644.       
  1645.       (ediff-refresh-mode-lines)
  1646.       
  1647.       ;; For diff2 jobs, don't recompute fine diffs, since we know there
  1648.       ;; aren't any. So we clear diffs after ediff-recenter.
  1649.       (if (and saved-p (not three-way))
  1650.       (ediff-clear-fine-differences n))
  1651.       ;; Make sure that the message about saving and how to restore is seen
  1652.       ;; by the user
  1653.       (message messg))
  1654.     ))
  1655.      
  1656. ;; Save Nth diff of buffer BUF-TYPE \(A, B, or C\).
  1657. ;; That is to say, the Nth diff on the `ediff-killed-diffs-alist'.  REG
  1658. ;; is the region to save.  It is redundant here, but is passed anyway, for
  1659. ;; convenience.
  1660. (defun ediff-save-diff-region (n buf-type reg)
  1661.   (let* ((n-th-diff-saved (assoc n ediff-killed-diffs-alist))
  1662.      (buf (ediff-get-buffer buf-type))
  1663.      (this-buf-n-th-diff-saved (assoc buf (cdr n-th-diff-saved))))
  1664.      
  1665.     (if this-buf-n-th-diff-saved
  1666.     ;; either nothing saved for n-th diff and buffer or we OK'ed
  1667.     ;; overriding
  1668.     (setcdr this-buf-n-th-diff-saved reg)
  1669.       (if n-th-diff-saved ;; n-th diff saved, but for another buffer
  1670.       (nconc n-th-diff-saved  (list (cons buf reg)))
  1671.     (setq ediff-killed-diffs-alist  ;; create record for n-th diff
  1672.           (cons (list n (cons buf reg))
  1673.             ediff-killed-diffs-alist))))
  1674.     (message "Saving old diff region #%d of buffer %S. To recover, type `r%s'"
  1675.          (1+ n) buf-type
  1676.          (if ediff-merge-job
  1677.          "" (downcase (symbol-name buf-type))))
  1678.     ))
  1679.     
  1680. ;; Test if saving Nth difference region of buffer BUF-TYPE is possible.
  1681. (defun ediff-test-save-region (n buf-type)
  1682.   (let* ((n-th-diff-saved (assoc n ediff-killed-diffs-alist))
  1683.      (buf (ediff-get-buffer buf-type))
  1684.      (this-buf-n-th-diff-saved (assoc buf (cdr n-th-diff-saved))))
  1685.      
  1686.     (if this-buf-n-th-diff-saved
  1687.     (if (yes-or-no-p
  1688.          (format 
  1689.           "You've previously copied diff region %d to buffer %S. Confirm "
  1690.           (1+ n) buf-type))
  1691.         t
  1692.       (error "Quit"))
  1693.       t)))
  1694.       
  1695. (defun ediff-pop-diff (n buf-type)
  1696.   "Pop last killed Nth diff region from buffer BUF-TYPE."
  1697.   (let* ((n-th-record (assoc n ediff-killed-diffs-alist))
  1698.      (buf (ediff-get-buffer buf-type))
  1699.      (saved-rec (assoc buf (cdr n-th-record)))
  1700.      (three-way ediff-3way-job)
  1701.      (ctl-buf ediff-control-buffer)
  1702.      ediff-verbose-p
  1703.      saved-diff reg-beg reg-end recovered)
  1704.     
  1705.     (if (cdr saved-rec)
  1706.     (setq saved-diff (cdr saved-rec))
  1707.       (if (> ediff-number-of-differences 0)
  1708.       (error "Nothing saved for diff %d in buffer %S" (1+ n) buf-type)
  1709.     (error "No differences found")))
  1710.     
  1711.     (setq reg-beg (ediff-get-diff-posn buf-type 'beg n ediff-control-buffer))
  1712.     (setq reg-end (ediff-get-diff-posn buf-type 'end n ediff-control-buffer))
  1713.     (setq ediff-disturbed-overlays nil) ; clear before use
  1714.     
  1715.     (condition-case conds
  1716.     (ediff-eval-in-buffer buf
  1717.       (let ((inhibit-read-only (null buffer-read-only)))
  1718.         ;; these two insert a dummy char to overcome a bug in XEmacs,
  1719.         ;; which sometimes prevents 0-length extents from sensing
  1720.         ;; insertion at its end-points.
  1721.         ;; (need to check if 19.12 still has the bug)
  1722.         (if ediff-xemacs-p
  1723.         (progn
  1724.           (goto-char reg-end)
  1725.           (insert-before-markers "@")))
  1726.         
  1727.         (goto-char reg-end)
  1728.         (insert-before-markers saved-diff)
  1729.         
  1730.         ;; delete dummy char
  1731.         (if ediff-xemacs-p
  1732.         (delete-char 1))
  1733.         
  1734.         (if ediff-xemacs-p
  1735.         (if (> reg-end reg-beg)
  1736.             (kill-region reg-beg reg-end))
  1737.           (if (> reg-end reg-beg)
  1738.           (kill-region reg-beg reg-end)
  1739.         (ediff-move-disturbed-overlays reg-beg)
  1740.         ))
  1741.         
  1742.         (setq recovered t)
  1743.         ))
  1744.       (error (message "ediff-pop-diff: %s %s"
  1745.               (car conds)
  1746.               (mapconcat 'prin1-to-string (cdr conds) " "))
  1747.          (beep 1)))
  1748.     
  1749.     ;; Clearing fine diffs is necessary for
  1750.     ;; ediff-unselect-and-select-difference to properly recompute them. We
  1751.     ;; can't rely on ediff-copy-diff to clear this vector, as the user might
  1752.     ;; have modified diff regions after copying and, thus, may have recomputed
  1753.     ;; fine diffs.
  1754.     (if recovered
  1755.     (ediff-clear-fine-differences n))
  1756.       
  1757.     ;; adjust state of difference
  1758.     (if (and three-way recovered)
  1759.     (ediff-set-state-of-diff-in-all-buffers n ctl-buf))
  1760.     
  1761.     (ediff-refresh-mode-lines)
  1762.     
  1763.     (if recovered
  1764.     (progn
  1765.       (setq n-th-record (delq saved-rec n-th-record))
  1766.       (message "Diff region %d in buffer %S restored" (1+ n) buf-type)
  1767.       ))
  1768.     ))
  1769.       
  1770. (defun ediff-restore-diff  (arg &optional key)
  1771.   "Restore ARGth diff from `ediff-killed-diffs-alist'.
  1772. ARG is a prefix argument.  If ARG is nil, restore current-difference.
  1773.  
  1774. If the second optional argument, a character, is given, use it to
  1775. determine the target buffer instead of last-command-char"
  1776.   (interactive "P")
  1777.   (if arg
  1778.       (ediff-jump-to-difference arg))
  1779.   (ediff-pop-diff ediff-current-difference 
  1780.           (ediff-char-to-buftype (or key last-command-char)))
  1781.   ;; recenter with rehighlighting, but no messages
  1782.   (let (ediff-verbose-p)
  1783.     (ediff-recenter)))
  1784.   
  1785. (defun ediff-toggle-regexp-match ()
  1786.   "Toggle between focusing and hiding of difference regions that match
  1787. a regular expression typed in by the user."
  1788.   (interactive)
  1789.   (let ((regexp-A "")
  1790.     (regexp-B "")
  1791.     (regexp-C "")
  1792.     msg-connective alt-msg-connective alt-connective)
  1793.     (cond
  1794.      ((or (and (eq ediff-skip-diff-region-function
  1795.            'ediff-focus-on-regexp-matches)
  1796.            (eq last-command-char ?f))
  1797.       (and (eq ediff-skip-diff-region-function 'ediff-hide-regexp-matches)
  1798.            (eq last-command-char ?h)))
  1799.       (message "Selective browsing by regexp turned off")
  1800.       (setq ediff-skip-diff-region-function 'ediff-show-all-diffs))
  1801.      ((eq last-command-char ?h)
  1802.       (setq ediff-skip-diff-region-function 'ediff-hide-regexp-matches
  1803.         regexp-A 
  1804.         (read-string
  1805.          (format 
  1806.           "Ignore A-regions matching this regexp (default \"%s\"): "
  1807.           ediff-regexp-hide-A))
  1808.         regexp-B
  1809.         (read-string
  1810.          (format 
  1811.           "Ignore B-regions matching this regexp (default \"%s\"): "
  1812.           ediff-regexp-hide-B)))
  1813.       (if ediff-3way-comparison-job
  1814.       (setq regexp-C
  1815.         (read-string
  1816.          (format 
  1817.           "Ignore C-regions matching this regexp (default \"%s\"): "
  1818.           ediff-regexp-hide-C))))
  1819.       (if (eq ediff-hide-regexp-connective 'and)
  1820.       (setq msg-connective "BOTH"
  1821.         alt-msg-connective "ONE OF"
  1822.         alt-connective 'or)
  1823.     (setq msg-connective "ONE OF"
  1824.           alt-msg-connective "BOTH"
  1825.           alt-connective 'and))
  1826.       (if (y-or-n-p
  1827.        (format
  1828.         "Hiding diff regions that match %s regexps. Use %s instead? "
  1829.         msg-connective alt-msg-connective))
  1830.       (progn
  1831.         (setq ediff-hide-regexp-connective alt-connective)
  1832.         (message "Hiding diff regions that match %s regexps"
  1833.              alt-msg-connective))
  1834.     (message "Hiding diff regions that match %s regexps" msg-connective))
  1835.       (or (string= regexp-A "") (setq ediff-regexp-hide-A regexp-A))
  1836.       (or (string= regexp-B "") (setq ediff-regexp-hide-B regexp-B))
  1837.       (or (string= regexp-C "") (setq ediff-regexp-hide-C regexp-C)))
  1838.      ((eq last-command-char ?f)
  1839.       (setq ediff-skip-diff-region-function 'ediff-focus-on-regexp-matches
  1840.         regexp-A 
  1841.         (read-string
  1842.          (format 
  1843.           "Focus on A-regions matching this regexp (default \"%s\"): "
  1844.           ediff-regexp-focus-A))
  1845.         regexp-B
  1846.         (read-string
  1847.          (format 
  1848.           "Focus on B-regions matching this regexp (default \"%s\"): "
  1849.           ediff-regexp-focus-B)))
  1850.       (if ediff-3way-comparison-job
  1851.       (setq regexp-C
  1852.         (read-string
  1853.          (format 
  1854.           "Focus on C-regions matching this regexp (default \"%s\"): "
  1855.           ediff-regexp-focus-C))))
  1856.       (if (eq ediff-focus-regexp-connective 'and)
  1857.       (setq msg-connective "BOTH"
  1858.         alt-msg-connective "ONE OF"
  1859.         alt-connective 'or)
  1860.     (setq msg-connective "ONE OF"
  1861.           alt-msg-connective "BOTH"
  1862.           alt-connective 'and))
  1863.       (if (y-or-n-p
  1864.        (format
  1865.         "Focusing on diff regions that match %s regexps. Use %s instead? "
  1866.         msg-connective alt-msg-connective))
  1867.       (progn
  1868.         (setq ediff-focus-regexp-connective alt-connective)
  1869.         (message "Focusing on diff regions that match %s regexps" 
  1870.              alt-msg-connective))
  1871.     (message "Focusing on diff regions that match %s regexps"
  1872.          msg-connective))
  1873.       (or (string= regexp-A "") (setq ediff-regexp-focus-A regexp-A))
  1874.       (or (string= regexp-B "") (setq ediff-regexp-focus-B regexp-B))
  1875.       (or (string= regexp-C "") (setq ediff-regexp-focus-C regexp-C))))))
  1876.       
  1877. (defun ediff-toggle-skip-similar ()
  1878.   (interactive)
  1879.   (if (not (eq ediff-auto-refine 'on))
  1880.       (error
  1881.        "Can't skip over whitespace regions: first turn auto-refining on"))
  1882.   (setq ediff-ignore-similar-regions (not ediff-ignore-similar-regions))
  1883.   (if ediff-ignore-similar-regions
  1884.       (message
  1885.        "Skipping regions that differ only in white space & line breaks")
  1886.     (message "Skipping over white-space differences turned off")))
  1887.   
  1888. (defun ediff-focus-on-regexp-matches (n)
  1889.   "Focus on diffs that match regexp `ediff-regexp-focus-A/B'.
  1890. Regions to be ignored according to this function are those where   
  1891. buf A region doesn't match `ediff-regexp-focus-A' and buf B region
  1892. doesn't match `ediff-regexp-focus-B'.
  1893. This function returns nil if the region number N (specified as
  1894. an argument) is not to be ignored and t if region N is to be ignored.
  1895.  
  1896. N is a region number used by Ediff internally. It is 1 less
  1897. the number seen by the user."
  1898.   (if (ediff-valid-difference-p n)
  1899.       (let* ((ctl-buf ediff-control-buffer)
  1900.          (regex-A ediff-regexp-focus-A)
  1901.          (regex-B ediff-regexp-focus-B)
  1902.          (regex-C ediff-regexp-focus-C)
  1903.          (reg-A-match (ediff-eval-in-buffer ediff-buffer-A
  1904.                 (goto-char (ediff-get-diff-posn 'A 'beg n ctl-buf))
  1905.                 (re-search-forward
  1906.                  regex-A
  1907.                  (ediff-get-diff-posn 'A 'end n ctl-buf)
  1908.                  t)))
  1909.          (reg-B-match (ediff-eval-in-buffer ediff-buffer-B
  1910.                 (goto-char (ediff-get-diff-posn 'B 'beg n ctl-buf))
  1911.                 (re-search-forward
  1912.                  regex-B
  1913.                  (ediff-get-diff-posn 'B 'end n ctl-buf)
  1914.                  t)))
  1915.          (reg-C-match (if ediff-3way-comparison-job
  1916.                   (ediff-eval-in-buffer ediff-buffer-C
  1917.                 (goto-char
  1918.                  (ediff-get-diff-posn 'C 'beg n ctl-buf))
  1919.                 (re-search-forward
  1920.                  regex-C
  1921.                  (ediff-get-diff-posn 'C 'end n ctl-buf)
  1922.                  t)))))
  1923.     (not (eval (if ediff-3way-comparison-job
  1924.                (list ediff-focus-regexp-connective
  1925.                  reg-A-match reg-B-match reg-C-match)
  1926.              (list ediff-focus-regexp-connective
  1927.                reg-A-match reg-B-match))))
  1928.     )))
  1929.   
  1930. (defun ediff-hide-regexp-matches (n)  
  1931.   "Hide diffs that match regexp `ediff-regexp-hide-A/B/C'.
  1932. Regions to be ignored are those where buf A region matches
  1933. `ediff-regexp-hide-A' and buf B region matches `ediff-regexp-hide-B'.
  1934. This function returns nil if the region number N (specified as
  1935. an argument) is not to be ignored and t if region N is to be ignored.
  1936.  
  1937. N is a region number used by Ediff internally. It is 1 less
  1938. the number seen by the user."
  1939.   (if (ediff-valid-difference-p n)
  1940.       (let* ((ctl-buf ediff-control-buffer)
  1941.          (regex-A ediff-regexp-hide-A)
  1942.          (regex-B ediff-regexp-hide-B)
  1943.          (regex-C ediff-regexp-hide-C)
  1944.          (reg-A-match (ediff-eval-in-buffer ediff-buffer-A
  1945.                 (goto-char (ediff-get-diff-posn 'A 'beg n ctl-buf))
  1946.                 (re-search-forward
  1947.                  regex-A
  1948.                  (ediff-get-diff-posn 'A 'end n ctl-buf)
  1949.                  t)))
  1950.          (reg-B-match (ediff-eval-in-buffer ediff-buffer-B
  1951.                 (goto-char (ediff-get-diff-posn 'B 'beg n ctl-buf))
  1952.                 (re-search-forward
  1953.                  regex-B
  1954.                  (ediff-get-diff-posn 'B 'end n ctl-buf)
  1955.                  t)))
  1956.          (reg-C-match (if ediff-3way-comparison-job
  1957.                   (ediff-eval-in-buffer ediff-buffer-C
  1958.                 (goto-char
  1959.                  (ediff-get-diff-posn 'C 'beg n ctl-buf))
  1960.                 (re-search-forward
  1961.                  regex-C
  1962.                  (ediff-get-diff-posn 'C 'end n ctl-buf)
  1963.                  t)))))
  1964.     (eval (if ediff-3way-comparison-job
  1965.           (list ediff-hide-regexp-connective
  1966.             reg-A-match reg-B-match reg-C-match)
  1967.         (list ediff-hide-regexp-connective reg-A-match reg-B-match)))
  1968.     )))
  1969.     
  1970.  
  1971.  
  1972. ;;; Quitting, suspending, etc.
  1973.  
  1974. (defun ediff-quit (reverse-default-keep-variants)
  1975.   "Finish an Ediff session and exit Ediff.
  1976. Unselects the selected difference, if any, restores the read-only and modified
  1977. flags of the compared file buffers, kills Ediff buffers for this session
  1978. \(but not buffers A, B, C\).
  1979.  
  1980. If `ediff-keep-variants' is nil, the user will be asked whether the buffers
  1981. containing the variants should be removed \(if they haven't been modified\). 
  1982. If it is t, they will be preserved unconditionally. A prefix argument, 
  1983. temporarily reverses the meaning of this variable."
  1984.   (interactive "P")
  1985.   (if (prog1
  1986.       (y-or-n-p
  1987.        (format "Quit this Ediff session%s? "
  1988.            (if (ediff-buffer-live-p ediff-meta-buffer)
  1989.                " & show containing session group" "")))
  1990.     (message ""))
  1991.       (ediff-really-quit reverse-default-keep-variants)))
  1992.  
  1993.  
  1994. ;; Perform the quit operations.
  1995. (defun ediff-really-quit (reverse-default-keep-variants)
  1996.   (ediff-unhighlight-diffs-totally)
  1997.   (ediff-clear-diff-vector 'ediff-difference-vector-A 'fine-diffs-also)
  1998.   (ediff-clear-diff-vector 'ediff-difference-vector-B 'fine-diffs-also)
  1999.   (ediff-clear-diff-vector 'ediff-difference-vector-C 'fine-diffs-also)
  2000.   (ediff-clear-diff-vector 'ediff-difference-vector-Ancestor 'fine-diffs-also)
  2001.   
  2002.   (ediff-delete-temp-files)
  2003.                   
  2004.   ;; Restore visibility range. This affects only ediff-*-regions/windows.
  2005.   ;; Since for other job names ediff-visible-region sets
  2006.   ;; ediff-visible-bounds to ediff-wide-bounds, the settings below are
  2007.   ;; ignored for such jobs.
  2008.   (if ediff-quit-widened
  2009.       (setq ediff-visible-bounds ediff-wide-bounds)
  2010.     (setq ediff-visible-bounds ediff-narrow-bounds))
  2011.   
  2012.   ;; Apply selective display to narrow or widen
  2013.   (ediff-visible-region)
  2014.   (mapcar (function (lambda (overl)
  2015.               (if (ediff-overlayp overl)
  2016.               (ediff-delete-overlay overl))))
  2017.       ediff-wide-bounds)
  2018.   (mapcar (function (lambda (overl)
  2019.               (if (ediff-overlayp overl)
  2020.               (ediff-delete-overlay overl))))
  2021.       ediff-narrow-bounds)
  2022.   
  2023.   ;; restore buffer mode line id's in buffer-A/B/C
  2024.   (let ((control-buffer ediff-control-buffer)
  2025.     (meta-buffer ediff-meta-buffer))
  2026.     (condition-case nil
  2027.     (ediff-eval-in-buffer ediff-buffer-A
  2028.       (setq ediff-this-buffer-ediff-sessions 
  2029.         (delq control-buffer ediff-this-buffer-ediff-sessions))
  2030.       (kill-local-variable 'mode-line-buffer-identification)
  2031.       (kill-local-variable 'mode-line-format)
  2032.       )
  2033.       (error))
  2034.       
  2035.     (condition-case nil
  2036.     (ediff-eval-in-buffer ediff-buffer-B
  2037.       (setq ediff-this-buffer-ediff-sessions 
  2038.         (delq control-buffer ediff-this-buffer-ediff-sessions))
  2039.       (kill-local-variable 'mode-line-buffer-identification)
  2040.       (kill-local-variable 'mode-line-format)
  2041.       )
  2042.       (error))
  2043.     
  2044.     (condition-case nil
  2045.     (ediff-eval-in-buffer ediff-buffer-C
  2046.       (setq ediff-this-buffer-ediff-sessions 
  2047.         (delq control-buffer ediff-this-buffer-ediff-sessions))
  2048.       (kill-local-variable 'mode-line-buffer-identification)
  2049.       (kill-local-variable 'mode-line-format)
  2050.       )
  2051.       (error))
  2052.  
  2053.     (condition-case nil
  2054.     (ediff-eval-in-buffer ediff-ancestor-buffer
  2055.       (setq ediff-this-buffer-ediff-sessions 
  2056.         (delq control-buffer ediff-this-buffer-ediff-sessions))
  2057.       (kill-local-variable 'mode-line-buffer-identification)
  2058.       (kill-local-variable 'mode-line-format)
  2059.       )
  2060.       (error))
  2061.  
  2062.   (setq ediff-session-registry
  2063.     (delq ediff-control-buffer ediff-session-registry))
  2064.   (ediff-update-registry)
  2065.   ;; restore state of buffers to what it was before ediff
  2066.   (ediff-restore-protected-variables)
  2067.   ;; good place to kill buffers A/B/C
  2068.   (run-hooks 'ediff-cleanup-hooks)
  2069.   (let ((ediff-keep-variants ediff-keep-variants))
  2070.     (if reverse-default-keep-variants
  2071.     (setq ediff-keep-variants (not ediff-keep-variants)))
  2072.     (or ediff-keep-variants (ediff-janitor 'ask)))
  2073.  
  2074.   (run-hooks 'ediff-quit-hooks)
  2075.   (ediff-cleanup-meta-buffer meta-buffer)
  2076.   (if (ediff-buffer-live-p meta-buffer)
  2077.       (ediff-show-meta-buffer meta-buffer))
  2078.   ))
  2079.   
  2080.   
  2081. (defun ediff-delete-temp-files ()
  2082.   (if (stringp ediff-temp-file-A)
  2083.       (delete-file ediff-temp-file-A))
  2084.   (if (stringp ediff-temp-file-B)
  2085.       (delete-file ediff-temp-file-B))
  2086.   (if (stringp ediff-temp-file-C)
  2087.       (delete-file ediff-temp-file-C)))
  2088.   
  2089.  
  2090. ;; Kill control buffer, other auxiliary Ediff buffers.
  2091. ;; Leave one of the frames split between buffers A/B/C
  2092. (defun ediff-cleanup-mess ()
  2093.   (let ((buff-A ediff-buffer-A)
  2094.     (buff-B ediff-buffer-B)
  2095.     (buff-C ediff-buffer-C)
  2096.     (ctl-buf  ediff-control-buffer)
  2097.     (ctl-frame ediff-control-frame)
  2098.     (three-way-job ediff-3way-job))
  2099.     
  2100.     (ediff-kill-buffer-carefully ediff-diff-buffer)
  2101.     (ediff-kill-buffer-carefully ediff-custom-diff-buffer)
  2102.     (ediff-kill-buffer-carefully ediff-fine-diff-buffer)
  2103.     (ediff-kill-buffer-carefully ediff-tmp-buffer)
  2104.     (ediff-kill-buffer-carefully ediff-error-buffer)
  2105.     (ediff-kill-buffer-carefully ediff-patch-diagnostics)
  2106.     (ediff-kill-buffer-carefully ediff-msg-buffer)
  2107.     (ediff-kill-buffer-carefully ediff-debug-buffer)
  2108.  
  2109.     ;;(redraw-display)
  2110.     (if (and (ediff-window-display-p) (frame-live-p ctl-frame))
  2111.     (delete-frame ctl-frame))
  2112.     (ediff-kill-buffer-carefully ctl-buf)
  2113.       
  2114.     (delete-other-windows)
  2115.     
  2116.     ;; display only if not visible
  2117.     (condition-case nil
  2118.     (or (ediff-get-visible-buffer-window buff-B)
  2119.         (switch-to-buffer buff-B))
  2120.       (error))
  2121.     (condition-case nil
  2122.     (or (ediff-get-visible-buffer-window buff-A)
  2123.         (progn
  2124.           (if (ediff-get-visible-buffer-window buff-B)
  2125.           (split-window-vertically))
  2126.           (switch-to-buffer buff-A)))
  2127.       (error))
  2128.     (if three-way-job
  2129.     (condition-case nil
  2130.         (or (ediff-get-visible-buffer-window buff-C)
  2131.         (progn
  2132.           (if (or (ediff-get-visible-buffer-window buff-A)
  2133.               (ediff-get-visible-buffer-window buff-B))
  2134.               (split-window-vertically))
  2135.           (switch-to-buffer buff-C)
  2136.           (balance-windows)))
  2137.       (error)))
  2138.     (message "")
  2139.     ))
  2140.  
  2141. (defun ediff-janitor (&optional ask)
  2142.   "Kill buffers A, B, and, possibly, C, if these buffers aren't modified.
  2143. In merge jobs, buffer C is never deleted.
  2144. However, the side effect of cleaning up may be that you cannot compare the same
  2145. buffer in two separate Ediff sessions: quitting one of them will delete this
  2146. buffer in another session as well."
  2147.   (or (not (ediff-buffer-live-p ediff-buffer-A))
  2148.       (buffer-modified-p ediff-buffer-A)
  2149.       (and ask
  2150.        (not (y-or-n-p (format "Kill buffer A [%s]? "
  2151.                   (buffer-name ediff-buffer-A)))))
  2152.       (ediff-kill-buffer-carefully ediff-buffer-A))
  2153.   (or (not (ediff-buffer-live-p ediff-buffer-B))
  2154.       (buffer-modified-p ediff-buffer-B)
  2155.       (and ask
  2156.        (not (y-or-n-p (format "Kill buffer B [%s]? "
  2157.                   (buffer-name ediff-buffer-B)))))
  2158.       (ediff-kill-buffer-carefully ediff-buffer-B))
  2159.   (if ediff-merge-job  ; don't del buf C if merging--del ancestor buf instead
  2160.       (or (not (ediff-buffer-live-p ediff-ancestor-buffer))
  2161.       (buffer-modified-p ediff-ancestor-buffer)
  2162.       (and ask
  2163.            (not (y-or-n-p (format "Kill the ancestor buffer [%s]? "
  2164.                       (buffer-name ediff-ancestor-buffer)))))
  2165.       (ediff-kill-buffer-carefully ediff-ancestor-buffer))
  2166.     (or (not (ediff-buffer-live-p ediff-buffer-C))
  2167.     (buffer-modified-p ediff-buffer-C)
  2168.     (and ask (not (y-or-n-p (format "Kill buffer C [%s]? "
  2169.                     (buffer-name ediff-buffer-C)))))
  2170.     (ediff-kill-buffer-carefully ediff-buffer-C))))
  2171.  
  2172. ;; The default way of suspending Ediff.
  2173. ;; Buries Ediff buffers, kills all windows.
  2174. (defun ediff-default-suspend-hook ()
  2175.   (let* ((buf-A ediff-buffer-A)
  2176.      (buf-B ediff-buffer-B)
  2177.      (buf-C ediff-buffer-C)
  2178.      (buf-A-wind (ediff-get-visible-buffer-window buf-A))
  2179.      (buf-B-wind (ediff-get-visible-buffer-window buf-B))
  2180.      (buf-C-wind (ediff-get-visible-buffer-window buf-C))
  2181.      (buf-patch ediff-patch-buf)
  2182.      (buf-patch-diag ediff-patch-diagnostics)
  2183.      (buf-err  ediff-error-buffer)
  2184.      (buf-diff ediff-diff-buffer)
  2185.      (buf-custom-diff ediff-custom-diff-buffer)
  2186.      (buf-fine-diff ediff-fine-diff-buffer))
  2187.     
  2188.     ;; hide the control panel
  2189.     (if (and (ediff-window-display-p) (frame-live-p ediff-control-frame))
  2190.     (iconify-frame ediff-control-frame)
  2191.       (bury-buffer)) 
  2192.     (if buf-err (bury-buffer buf-err))
  2193.     (if buf-diff (bury-buffer buf-diff))
  2194.     (if buf-custom-diff (bury-buffer buf-custom-diff))
  2195.     (if buf-fine-diff (bury-buffer buf-fine-diff))
  2196.     (if buf-patch (bury-buffer buf-patch))
  2197.     (if buf-patch-diag (bury-buffer buf-patch-diag))
  2198.     (if (window-live-p buf-A-wind)
  2199.     (progn
  2200.       (select-window buf-A-wind)
  2201.       (delete-other-windows)
  2202.       (bury-buffer))
  2203.       (if (ediff-buffer-live-p buf-A) (bury-buffer buf-A)))
  2204.     (if (window-live-p buf-B-wind)
  2205.     (progn
  2206.       (select-window buf-B-wind)
  2207.       (delete-other-windows)
  2208.       (bury-buffer))
  2209.       (if (ediff-buffer-live-p buf-B) (bury-buffer buf-B)))
  2210.     (if (window-live-p buf-C-wind)
  2211.     (progn
  2212.       (select-window buf-C-wind)
  2213.       (delete-other-windows)
  2214.       (bury-buffer))
  2215.       (if (ediff-buffer-live-p buf-C) (bury-buffer buf-C)))
  2216.  
  2217.     ))
  2218.  
  2219.      
  2220. (defun ediff-suspend ()
  2221.   "Suspend Ediff.
  2222. To resume, switch to the appropriate `Ediff Control Panel'
  2223. buffer and then type \\[ediff-recenter].  Ediff will automatically set
  2224. up an appropriate window config."
  2225.   (interactive)
  2226.   (let ((key (substitute-command-keys "\\[ediff-recenter]")))
  2227.   (run-hooks 'ediff-suspend-hooks)
  2228.   (message
  2229.    "To resume, switch to Ediff Control Panel and hit `%s'" key)))
  2230.  
  2231.  
  2232. (defun ediff-status-info ()
  2233.   "Show the names of the buffers or files being operated on by Ediff.
  2234. Hit \\[ediff-recenter] to reset the windows afterward."
  2235.   (interactive)
  2236.   (save-excursion
  2237.     (ediff-skip-unsuitable-frames))
  2238.   (with-output-to-temp-buffer " *ediff-info*"
  2239.     (princ (ediff-version))
  2240.     (princ "\n\n")
  2241.     (ediff-eval-in-buffer ediff-buffer-A
  2242.       (if buffer-file-name
  2243.       (princ
  2244.        (format "File A = %S\n" buffer-file-name))
  2245.     (princ 
  2246.      (format "Buffer A = %S\n" (buffer-name)))))
  2247.     (ediff-eval-in-buffer ediff-buffer-B
  2248.       (if buffer-file-name
  2249.       (princ
  2250.        (format "File B = %S\n" buffer-file-name))
  2251.     (princ 
  2252.      (format "Buffer B = %S\n" (buffer-name)))))
  2253.     (if ediff-3way-job
  2254.     (ediff-eval-in-buffer ediff-buffer-C
  2255.       (if buffer-file-name
  2256.           (princ
  2257.            (format "File C = %S\n" buffer-file-name))
  2258.         (princ 
  2259.          (format "Buffer C = %S\n" (buffer-name))))))
  2260.     (princ (format "Customized diff output %s\n"
  2261.            (if (ediff-buffer-live-p ediff-custom-diff-buffer)
  2262.                (concat "\tin buffer "
  2263.                    (buffer-name ediff-custom-diff-buffer))
  2264.              "is not available")))
  2265.     (princ (format "Plain diff output %s\n"
  2266.            (if (ediff-buffer-live-p ediff-diff-buffer)
  2267.                (concat "\tin buffer "
  2268.                    (buffer-name ediff-diff-buffer))
  2269.              "is not available")))
  2270.                   
  2271.     (let* ((A-line (ediff-eval-in-buffer ediff-buffer-A
  2272.              (1+ (count-lines (point-min) (point)))))
  2273.        (B-line (ediff-eval-in-buffer ediff-buffer-B
  2274.              (1+ (count-lines (point-min) (point)))))
  2275.        C-line)
  2276.       (princ (format "\Buffer A's point is on line %d\n" A-line))
  2277.       (princ (format "Buffer B's point is on line %d\n" B-line))
  2278.       (if ediff-3way-job
  2279.       (progn
  2280.         (setq C-line (ediff-eval-in-buffer ediff-buffer-C
  2281.                (1+ (count-lines (point-min) (point)))))
  2282.         (princ (format "Buffer C's point is on line %d\n" C-line)))))
  2283.       
  2284.     (princ (format "\nCurrent difference number = %S\n"
  2285.            (cond ((< ediff-current-difference 0) 'start)
  2286.              ((>= ediff-current-difference
  2287.                   ediff-number-of-differences) 'end)
  2288.              (t (1+ ediff-current-difference)))))
  2289.  
  2290.     (cond (ediff-ignore-similar-regions
  2291.        (princ "\nSkipping regions that differ only in white space & line breaks"))
  2292.       (t 
  2293.        (princ "\nNot skipping regions that differ in white space & line breaks")))
  2294.     
  2295.     (cond ((eq ediff-skip-diff-region-function 'ediff-show-all-diffs)
  2296.        (princ "\nSelective browsing by regexp is off.\n"))
  2297.       ((eq ediff-skip-diff-region-function 'ediff-hide-regexp-matches)
  2298.        (princ
  2299.         "\nIgnoring regions that match")
  2300.        (princ
  2301.         (format 
  2302.          "\n\t regexp `%s' in buffer A  %S\n\t regexp `%s' in buffer B\n"
  2303.          ediff-regexp-hide-A ediff-hide-regexp-connective
  2304.          ediff-regexp-hide-B)))
  2305.       ((eq ediff-skip-diff-region-function 'ediff-focus-on-regexp-matches)
  2306.        (princ
  2307.         "\nFocusing on regions that match")
  2308.        (princ
  2309.         (format
  2310.          "\n\t regexp `%s' in buffer A  %S\n\t regexp `%s' in buffer B\n"
  2311.          ediff-regexp-focus-A ediff-focus-regexp-connective
  2312.          ediff-regexp-focus-B)))
  2313.       (t (princ "\nSelective browsing via a user-defined method.\n")))
  2314.     
  2315.     (princ
  2316.      (format "\nBugs/suggestions: type `%s' while in Ediff Control Panel."
  2317.          (substitute-command-keys "\\[ediff-submit-report]")))
  2318.     ) ; with output
  2319.   (if (frame-live-p ediff-control-frame)
  2320.       (ediff-reset-mouse ediff-control-frame))
  2321.   (if (window-live-p ediff-control-window)
  2322.       (select-window ediff-control-window)))
  2323.     
  2324. (defun ediff-documentation ()
  2325.   "Jump to Ediff's Info file."
  2326.   (interactive)
  2327.   (let ((ctl-window ediff-control-window)
  2328.     (ctl-buf ediff-control-buffer))
  2329.  
  2330.     (ediff-skip-unsuitable-frames)
  2331.     (condition-case nil
  2332.     (progn
  2333.       (pop-to-buffer (get-buffer-create "*info*"))
  2334.       (info "ediff.info")
  2335.       (message "Type `i' to search for a specific topic"))
  2336.       (error (beep 1)
  2337.          (with-output-to-temp-buffer " *ediff-info*"
  2338.            (princ (format "
  2339. The Info file for Ediff does not seem to be installed.
  2340.  
  2341. This file is part of the distribution of %sEmacs.
  2342. Please contact your system administrator. "
  2343.                   (if ediff-xemacs-p "X" ""))))
  2344.          (if (window-live-p ctl-window)
  2345.          (progn
  2346.            (select-window ctl-window)
  2347.            (set-window-buffer ctl-window ctl-buf)))))))
  2348.     
  2349.  
  2350.  
  2351.  
  2352. ;;; Support routines
  2353.  
  2354. ;; Select a difference by placing the ASCII flags around the appropriate
  2355. ;; group of lines in the A, B buffers
  2356. ;; This may have to be modified for buffer C, when it will be supported.
  2357. (defun ediff-select-difference (n)
  2358.   (if (and (ediff-buffer-live-p ediff-buffer-A)
  2359.        (ediff-buffer-live-p ediff-buffer-B)
  2360.        (ediff-valid-difference-p n))
  2361.       (progn
  2362.     (if (and (ediff-window-display-p) ediff-use-faces)
  2363.         (progn
  2364.           (ediff-highlight-diff n)
  2365.           (setq ediff-highlighting-style 'face))
  2366.       (setq ediff-highlighting-style 'ascii)
  2367.       (ediff-place-flags-in-buffer
  2368.        'A ediff-buffer-A ediff-control-buffer n)
  2369.       (ediff-place-flags-in-buffer
  2370.        'B ediff-buffer-B ediff-control-buffer n)
  2371.       (if ediff-3way-job
  2372.           (ediff-place-flags-in-buffer
  2373.            'C ediff-buffer-C ediff-control-buffer n))
  2374.       (if (ediff-buffer-live-p ediff-ancestor-buffer)
  2375.           (ediff-place-flags-in-buffer
  2376.            'Ancestor ediff-ancestor-buffer
  2377.            ediff-control-buffer n))
  2378.       ) 
  2379.                        
  2380.     (ediff-install-fine-diff-if-necessary n)
  2381.     (run-hooks 'ediff-select-hooks))))
  2382.     
  2383.  
  2384. ;; Unselect a difference by removing the ASCII flags in the buffers.
  2385. ;; This may have to be modified for buffer C, when it will be supported.
  2386. (defun ediff-unselect-difference (n)
  2387.   (if (ediff-valid-difference-p n)
  2388.       (progn 
  2389.     (cond ((and (ediff-window-display-p) ediff-use-faces)
  2390.            (ediff-unhighlight-diff))
  2391.           ((eq ediff-highlighting-style 'ascii)
  2392.            (ediff-remove-flags-from-buffer
  2393.         ediff-buffer-A
  2394.         (ediff-get-diff-overlay n 'A))
  2395.            (ediff-remove-flags-from-buffer
  2396.         ediff-buffer-B
  2397.         (ediff-get-diff-overlay n 'B))
  2398.            (if ediff-3way-job
  2399.            (ediff-remove-flags-from-buffer
  2400.             ediff-buffer-C
  2401.             (ediff-get-diff-overlay n 'C)))
  2402.            (if (ediff-buffer-live-p ediff-ancestor-buffer)
  2403.            (ediff-remove-flags-from-buffer
  2404.             ediff-ancestor-buffer
  2405.             (ediff-get-diff-overlay n 'Ancestor)))
  2406.            ))
  2407.     (setq ediff-highlighting-style nil)
  2408.     
  2409.     ;; unhighlight fine diffs
  2410.     (ediff-set-fine-diff-properties ediff-current-difference 'default)
  2411.     (run-hooks 'ediff-unselect-hooks))))
  2412.   
  2413.  
  2414. ;; Unselects prev diff and selects a new one, if FLAG has value other than
  2415. ;; 'select-only or 'unselect-only.  If FLAG is 'select-only, the
  2416. ;; next difference is selected, but the current selection is not
  2417. ;; unselected.  If FLAG is 'unselect-only then the current selection is
  2418. ;; unselected, but the next one is not selected.  If NO-RECENTER is non-nil,
  2419. ;; don't recenter buffers after selecting/unselecting.
  2420. (defun ediff-unselect-and-select-difference (n &optional flag no-recenter)
  2421.   (let ((ediff-current-difference n))
  2422.     (or no-recenter
  2423.     (ediff-recenter 'no-rehighlight)))
  2424.       
  2425.   (let ((control-buf ediff-control-buffer))
  2426.     (unwind-protect    
  2427.     (progn
  2428.       (or (eq flag 'select-only)
  2429.           (ediff-unselect-difference ediff-current-difference))
  2430.       
  2431.       (or (eq flag 'unselect-only)
  2432.           (ediff-select-difference n))
  2433.       (setq ediff-current-difference n)
  2434.       ) ; end protected section
  2435.       
  2436.       (ediff-eval-in-buffer control-buf
  2437.     (ediff-refresh-mode-lines))
  2438.       )))
  2439.  
  2440.  
  2441. (defun ediff-read-file-name (prompt default-dir default-file)
  2442. ; This is a modified version of a similar function in `emerge.el'.
  2443. ; PROMPT should not have trailing ': ', so that it can be modified
  2444. ; according to context.
  2445. ; If default-file is set, it should be used as the default value.
  2446. ; If default-dir is non-nil, use it as the default directory.
  2447. ; Otherwise, use the value of Emacs' variable `default-directory.'
  2448.  
  2449.   ;; hack default-dir if it is not set
  2450.   (setq default-dir
  2451.     (file-name-as-directory
  2452.      (ediff-abbreviate-file-name
  2453.       (expand-file-name (or default-dir
  2454.                 (and default-file
  2455.                      (file-name-directory default-file))
  2456.                 default-directory)))))
  2457.  
  2458.   ;; strip the directory from default-file
  2459.   (if default-file
  2460.       (setq default-file (file-name-nondirectory default-file)))
  2461.   (if (string= default-file "")
  2462.       (setq default-file nil))
  2463.  
  2464.   (let (f)
  2465.     (setq f (expand-file-name
  2466.          (read-file-name
  2467.           (format "%s%s: "
  2468.               prompt
  2469.               (if default-file
  2470.               (concat " (default " default-file ")")
  2471.             ""))
  2472.           default-dir
  2473.           default-file
  2474.           t  ; must match, no-confirm
  2475.           (if default-file (file-name-directory default-file))
  2476.           )
  2477.          default-dir
  2478.          ))
  2479.     ;; If user enters a directory name, expand the default file in that
  2480.     ;; directory.  This allows the user to enter a directory name for the
  2481.     ;; B-file and diff against the default-file in that directory instead
  2482.     ;; of a DIRED listing!
  2483.     (if (and (file-directory-p f) default-file)
  2484.     (setq f (expand-file-name
  2485.          (file-name-nondirectory default-file) f)))
  2486.     f)) 
  2487.   
  2488. ;; If `prefix' is given, then it is used as a prefix for the temp file
  2489. ;; name. Otherwise, `ediff_' is used. If `file' is given, use this
  2490. ;; file and don't create a new one.
  2491. ;; Also, save buffer from START to END in the file.
  2492. ;; START defaults to (point-min), END to (point-max)
  2493. (defun ediff-make-temp-file (buff &optional prefix given-file start end)
  2494.   (let ((f (or given-file
  2495.            (make-temp-name (concat
  2496.                 ediff-temp-file-prefix
  2497.                 (if prefix
  2498.                     (concat prefix "_")
  2499.                     "ediff_"))))))
  2500.     ;; create the file
  2501.     (ediff-eval-in-buffer buff
  2502.       (write-region (if start start (point-min))
  2503.             (if end end (point-max))
  2504.             f
  2505.             nil          ; don't append---erase
  2506.             'no-message) 
  2507.       (set-file-modes f ediff-temp-file-mode)
  2508.       f)))
  2509.  
  2510. ;; Quote metacharacters (using \) when executing diff in Unix, but not in
  2511. ;; EMX OS/2
  2512. ;;(defun ediff-protect-metachars (str)
  2513. ;;  (or (memq system-type '(emx vax-vms axp-vms))
  2514. ;;      (let ((limit 0))
  2515. ;;    (while (string-match ediff-metachars str limit)
  2516. ;;      (setq str (concat (substring str 0 (match-beginning 0))
  2517. ;;                "\\"
  2518. ;;                (substring str (match-beginning 0))))
  2519. ;;      (setq limit (1+ (match-end 0))))))
  2520. ;;  str)
  2521.  
  2522. ;; Make sure the current buffer (for a file) has the same contents as the
  2523. ;; file on disk, and attempt to remedy the situation if not.
  2524. ;; Signal an error if we can't make them the same, or the user doesn't want
  2525. ;; to do what is necessary to make them the same.
  2526. ;; If file has file handlers (indicated by the optional arg), then we
  2527. ;; offer to instead of saving. This is one difference with Emerge. 
  2528. ;; Another is that we always offer to revert obsolete files, whether they
  2529. ;; are modified or not.
  2530. (defun ediff-verify-file-buffer (&optional file-magic)
  2531.   ;; First check if the file has been modified since the buffer visited it.
  2532.   (if (verify-visited-file-modtime (current-buffer))
  2533.       (if (buffer-modified-p)
  2534.       ;; If buffer is not obsolete and is modified, offer to save
  2535.       (if (yes-or-no-p 
  2536.            (format "Buffer out of sync with visited file. %s file %s? "
  2537.                (if file-magic "Revert" "Save")
  2538.                buffer-file-name))
  2539.           (if (not file-magic)
  2540.           (save-buffer)
  2541.         ;; for some reason, file-name-handlers append instead of
  2542.         ;; replacing, so we have to erase first.
  2543.         (erase-buffer)
  2544.         (revert-buffer t t))
  2545.         (error "Buffer out of sync for file %s" buffer-file-name))
  2546.     ;; If buffer is not obsolete and is not modified, do nothing
  2547.     nil)
  2548.     ;; If buffer is obsolete, offer to revert
  2549.     (if (yes-or-no-p
  2550.      (format "Buffer out of sync with visited file. Revert file %s? "
  2551.          buffer-file-name))
  2552.     (progn
  2553.       (if file-magic
  2554.           (erase-buffer))
  2555.       (revert-buffer t t))
  2556.       (error "Buffer out of sync for file %s" buffer-file-name))))
  2557.  
  2558.  
  2559.  
  2560. ;; It would be nice to use these two functions as hooks instead of
  2561. ;; ediff-insert-in-front and ediff-move-disturbed-overlays.
  2562. ;; However, Emacs has a bug that causes BEG and END, below, to be
  2563. ;; the same, i.e., the end of inserted text is not passed correctly.
  2564. ;; Since the overlay doesn't move when these hooks run, 
  2565. ;; there is no way to correctly determine the new (desired) position of
  2566. ;; the overlay end.
  2567. ;; Either this bug is fixed, or (better) use sticky overlays when they will
  2568. ;; be implemented in Emacs, like they are in XEmacs.
  2569. ;;(defun ediff-capture-inserts-in-front (overl beg end)
  2570. ;;  (if (ediff-overlay-get overl 'ediff-diff-num)
  2571. ;;      (ediff-move-overlay
  2572. ;;       overl beg (+ (- end beg) (ediff-overlay-end overl)))
  2573. ;;  ))
  2574. ;;(defun ediff-capture-inserts-behind (overl beg end)
  2575. ;;  (if (ediff-overlay-get overl 'ediff-diff-num)
  2576. ;;      (ediff-move-overlay overl (ediff-overlay-start overl) end))
  2577. ;;  ))
  2578.   
  2579. ;; to be deleted in due time
  2580. ;; Capture overlays that had insertions in the front.
  2581. ;; Called when overlay OVERL gets insertion in front.
  2582. (defun ediff-insert-in-front (overl &optional flag beg end length)
  2583.   (if (ediff-overlay-get overl 'ediff-diff-num)
  2584.       (setq ediff-disturbed-overlays
  2585.         (cons overl ediff-disturbed-overlays))))
  2586.   
  2587.   
  2588. ;; to be deleted in due time
  2589. ;; We can't move overlays directly in insert-in-front-hooks
  2590. ;; because when diff is highlighted  with ascii flags, they will  disturb
  2591. ;; overlays and so they will be included in them, which we don't want.
  2592. (defun  ediff-move-disturbed-overlays (posn)  
  2593.   (mapcar (function (lambda (overl)
  2594.                (ediff-move-overlay overl
  2595.                        posn
  2596.                        (ediff-overlay-end overl))
  2597.                ))
  2598.       ediff-disturbed-overlays)
  2599.   (setq ediff-disturbed-overlays nil))
  2600.   
  2601.   
  2602. (defun ediff-save-buffer (arg)
  2603.   "Safe way of saving buffers A, B, C, and the diff output.
  2604. `wa' saves buffer A, `wb' saves buffer B, `wc' saves buffer C,
  2605. and `wd' saves the diff output.
  2606.  
  2607. With prefix argument, `wd' saves plain diff output.
  2608. Without an argument, it saves customized diff argument, if available
  2609. \(and plain output, if customized output was not generated\)."
  2610.   (interactive "P")
  2611.   (ediff-compute-custom-diffs-maybe)
  2612.   (ediff-eval-in-buffer
  2613.       (cond ((memq last-command-char '(?a ?b ?c))
  2614.          (ediff-get-buffer
  2615.           (ediff-char-to-buftype last-command-char)))
  2616.         ((eq last-command-char ?d)
  2617.          (message "Saving diff output ...")
  2618.          (sit-for 1) ; let the user see the message
  2619.          (cond ((and arg (ediff-buffer-live-p ediff-diff-buffer))
  2620.             ediff-diff-buffer)
  2621.            ((ediff-buffer-live-p ediff-custom-diff-buffer)
  2622.             ediff-custom-diff-buffer)
  2623.            ((ediff-buffer-live-p ediff-diff-buffer)
  2624.             ediff-diff-buffer)
  2625.            (t (error "Output from `diff' not found"))))
  2626.         )
  2627.     (save-buffer)))
  2628.  
  2629. (defun ediff-compute-custom-diffs-maybe ()
  2630.   (or ediff-3way-job
  2631.       (let ((file-A (ediff-make-temp-file ediff-buffer-A))
  2632.         (file-B (ediff-make-temp-file ediff-buffer-B)))
  2633.     (or (ediff-buffer-live-p ediff-custom-diff-buffer)
  2634.         (setq ediff-custom-diff-buffer
  2635.           (get-buffer-create
  2636.            (ediff-unique-buffer-name "*ediff-custom-diff" "*"))))
  2637.     (ediff-exec-process
  2638.      ediff-custom-diff-program ediff-custom-diff-buffer 'synchronize
  2639.      ediff-custom-diff-options file-A file-B))))
  2640.  
  2641. (defun ediff-show-diff-output (arg)
  2642.   (interactive "P")
  2643.   (ediff-compute-custom-diffs-maybe)
  2644.   (save-excursion
  2645.     (ediff-skip-unsuitable-frames ' ok-unsplittable))
  2646.   (let ((buf (cond ((and arg (ediff-buffer-live-p ediff-diff-buffer))
  2647.             ediff-diff-buffer)
  2648.            ((ediff-buffer-live-p ediff-custom-diff-buffer)
  2649.             ediff-custom-diff-buffer)
  2650.            ((ediff-buffer-live-p ediff-diff-buffer)
  2651.             ediff-diff-buffer)
  2652.            (t
  2653.             (beep)
  2654.             (message "Output from `diff' not found")
  2655.             nil))))
  2656.     (if buf
  2657.     (progn
  2658.       (ediff-eval-in-buffer buf
  2659.         (goto-char (point-min)))
  2660.       (switch-to-buffer buf)
  2661.       (raise-frame (selected-frame)))))
  2662.   (if (frame-live-p ediff-control-frame)
  2663.       (ediff-reset-mouse ediff-control-frame))
  2664.   (if (window-live-p ediff-control-window)
  2665.       (select-window ediff-control-window)))
  2666.       
  2667.     
  2668.  
  2669. ;; will simplify it in due time, when emacs acquires before/after strings
  2670. (defun ediff-remove-flags-from-buffer (buffer overlay)
  2671.   (ediff-eval-in-buffer buffer
  2672.     (let ((inhibit-read-only t))
  2673.       (if ediff-xemacs-p
  2674.       (ediff-overlay-put overlay 'begin-glyph nil)
  2675.     ;; before-string is not yet implemented in emacs.
  2676.     ;; when it will be, I will be able to delete much of the rest of
  2677.     ;; this function
  2678.     (ediff-overlay-put overlay 'before-string nil))
  2679.       
  2680.       (if ediff-xemacs-p
  2681.       (ediff-overlay-put overlay 'end-glyph nil)
  2682.     ;; after-string is not yet implemented in emacs.
  2683.     (ediff-overlay-put overlay 'after-string nil))
  2684.       )))
  2685.  
  2686.  
  2687.  
  2688. ;; will simplify it in due time, when emacs acquires before/after strings
  2689. (defun ediff-place-flags-in-buffer (buf-type buffer ctl-buffer diff)
  2690.   (ediff-eval-in-buffer buffer
  2691.     (ediff-place-flags-in-buffer1 buf-type ctl-buffer diff)))
  2692.  
  2693.  
  2694. (defun ediff-place-flags-in-buffer1 (buf-type ctl-buffer diff-no)
  2695.   (let* ((curr-overl (ediff-eval-in-buffer ctl-buffer
  2696.                (ediff-get-diff-overlay diff-no buf-type)))
  2697.      (before (ediff-get-diff-posn buf-type 'beg diff-no ctl-buffer))
  2698.      after beg-of-line flag)
  2699.     
  2700.     ;; insert flag before the difference
  2701.     (goto-char before)
  2702.     (setq beg-of-line (bolp))
  2703.     
  2704.     (setq flag (ediff-eval-in-buffer ctl-buffer
  2705.          (if (eq ediff-highlighting-style 'ascii)
  2706.              (if beg-of-line
  2707.              ediff-before-flag-bol ediff-before-flag-mol))))
  2708.     
  2709.     ;; insert the flag itself
  2710.     (if ediff-xemacs-p
  2711.     (ediff-overlay-put curr-overl 'begin-glyph flag)
  2712.       (ediff-overlay-put curr-overl 'before-string flag))
  2713.     
  2714.     ;; insert the flag after the difference
  2715.     ;; `after' must be set here, after the before-flag was inserted
  2716.     (setq after (ediff-get-diff-posn buf-type 'end diff-no ctl-buffer))
  2717.     (goto-char after)
  2718.     (setq beg-of-line (bolp))
  2719.     
  2720.     (setq flag (ediff-eval-in-buffer ctl-buffer
  2721.          (if (eq ediff-highlighting-style 'ascii)
  2722.              (if beg-of-line
  2723.              ediff-after-flag-eol ediff-after-flag-mol))))
  2724.     
  2725.     ;; insert the flag itself
  2726.     (if ediff-xemacs-p
  2727.     (ediff-overlay-put curr-overl 'end-glyph flag)
  2728.       (ediff-overlay-put curr-overl 'after-string flag))
  2729.     ))
  2730.  
  2731.   
  2732. (defun ediff-get-diff-posn (buf-type pos &optional n control-buf)
  2733.   "Returns positions of difference sectors in the BUF-TYPE buffer.
  2734. BUF-TYPE should be a symbol--either `A' or `B'. 
  2735. POS is either `beg' or `end'--it specifies whether you want the position at the
  2736. beginning of a difference or at the end.
  2737.  
  2738. The optional argument N says which difference \(default:
  2739. `ediff-current-difference'\).  The optional argument CONTROL-BUF says
  2740. which control buffer is in effect in case it is not the current
  2741. buffer."
  2742.   (let (diff-overlay)
  2743.     (or control-buf
  2744.     (setq control-buf (current-buffer)))
  2745.  
  2746.     (ediff-eval-in-buffer control-buf
  2747.       (or n  (setq n ediff-current-difference))
  2748.       (if (or (< n 0) (>= n ediff-number-of-differences))
  2749.       (if (> ediff-number-of-differences 0)
  2750.           (error "There is no diff %d. Valid diffs are 1 to %d"
  2751.              (1+ n) ediff-number-of-differences)
  2752.         (error "No differences found")))
  2753.       (setq diff-overlay (ediff-get-diff-overlay n buf-type)))
  2754.     (if (not (ediff-buffer-live-p (ediff-overlay-buffer diff-overlay)))
  2755.     (error
  2756.      "You have killed an essential Ediff buffer---Please exit Ediff"))
  2757.     (if (eq pos 'beg)
  2758.     (ediff-overlay-start diff-overlay)
  2759.       (ediff-overlay-end diff-overlay))
  2760.     ))
  2761.  
  2762.  
  2763.  
  2764. (defun ediff-highlight-diff-in-one-buffer (n buf-type)
  2765.   (if (ediff-buffer-live-p (ediff-get-buffer buf-type))
  2766.       (let* ((buff (ediff-get-buffer buf-type))
  2767.          (last (ediff-eval-in-buffer buff (point-max)))
  2768.          (begin (ediff-get-diff-posn buf-type 'beg n))
  2769.          (end (ediff-get-diff-posn buf-type 'end n))
  2770.          (xtra (if (equal begin end) 1 0))
  2771.          (end-hilit (min last (+ end xtra)))
  2772.          (current-diff-overlay 
  2773.           (symbol-value
  2774.            (intern (format "ediff-current-diff-overlay-%S" buf-type))))
  2775.          )
  2776.     
  2777.     (if ediff-xemacs-p
  2778.         (ediff-move-overlay current-diff-overlay begin end-hilit)
  2779.       (ediff-move-overlay current-diff-overlay begin end-hilit buff))
  2780.     ;; giving priority of 0 and then changing it may look funny, but
  2781.     ;; this overcomes an obscure Emacs bug.
  2782.     (ediff-overlay-put current-diff-overlay 'priority  0)
  2783.     (ediff-overlay-put current-diff-overlay 'priority  
  2784.                (ediff-highest-priority begin end-hilit buff))
  2785.     (ediff-overlay-put current-diff-overlay 'ediff-diff-num n)
  2786.     
  2787.     ;; unhighlight the background overlay for diff n so it won't
  2788.     ;; interfere with the current diff overlay
  2789.     (ediff-set-overlay-face (ediff-get-diff-overlay n buf-type) nil)
  2790.     )))
  2791.  
  2792.  
  2793. (defun ediff-unhighlight-diff-in-one-buffer (buf-type)
  2794.   (if (ediff-buffer-live-p (ediff-get-buffer buf-type))
  2795.       (let ((current-diff-overlay 
  2796.          (symbol-value
  2797.           (intern (format "ediff-current-diff-overlay-%S" buf-type))))
  2798.         (overlay
  2799.          (ediff-get-diff-overlay ediff-current-difference buf-type))
  2800.         )
  2801.     
  2802.     (ediff-move-overlay current-diff-overlay 1 1)
  2803.     
  2804.     ;; rehighlight the overlay in the background of the
  2805.     ;; current difference region
  2806.     (ediff-set-overlay-face
  2807.      overlay
  2808.      (if (and (ediff-window-display-p)
  2809.           ediff-use-faces ediff-highlight-all-diffs)
  2810.          (ediff-background-face buf-type ediff-current-difference)))
  2811.     )))
  2812.  
  2813. (defun ediff-unhighlight-diffs-totally-in-one-buffer (buf-type)
  2814.   (ediff-unselect-and-select-difference -1)
  2815.   (if (and (ediff-window-display-p) ediff-use-faces)
  2816.       (let* ((inhibit-quit t)
  2817.          (current-diff-overlay-var
  2818.           (intern (format "ediff-current-diff-overlay-%S" buf-type)))
  2819.          (current-diff-overlay (symbol-value current-diff-overlay-var)))
  2820.     (ediff-color-background-regions 'unhighlight)
  2821.     (if (ediff-overlayp current-diff-overlay)
  2822.         (ediff-delete-overlay current-diff-overlay))
  2823.     (set current-diff-overlay-var nil)
  2824.     )))
  2825.  
  2826.     
  2827. ;; null out difference overlays so they won't slow down future
  2828. ;; editing operations
  2829. ;; VEC is either a difference vector or a fine-diff vector
  2830. (defun ediff-clear-diff-vector (vec-var &optional fine-diffs-also)
  2831.   (if (vectorp (symbol-value vec-var))
  2832.       (mapcar (function
  2833.            (lambda (elt)
  2834.          (ediff-delete-overlay 
  2835.           (ediff-get-diff-overlay-from-diff-record elt))
  2836.          (if fine-diffs-also
  2837.              (ediff-clear-fine-diff-vector elt))
  2838.          ))
  2839.           (symbol-value vec-var)))
  2840.   ;; allow them to be garbage collected
  2841.   (set vec-var nil))
  2842.  
  2843. (defun ediff-color-background-regions (&optional unhighlight)
  2844.   (ediff-color-background-regions-in-one-buffer
  2845.    'A unhighlight)
  2846.   (ediff-color-background-regions-in-one-buffer
  2847.    'B unhighlight)
  2848.   (ediff-color-background-regions-in-one-buffer
  2849.    'C unhighlight)
  2850.   (ediff-color-background-regions-in-one-buffer
  2851.    'Ancestor unhighlight))
  2852.  
  2853. (defun ediff-color-background-regions-in-one-buffer (buf-type unhighlight)
  2854.   (let ((diff-vector 
  2855.      (eval (intern (format "ediff-difference-vector-%S" buf-type))))
  2856.     overl diff-num)
  2857.     (mapcar (function
  2858.          (lambda (rec)
  2859.            (setq overl (ediff-get-diff-overlay-from-diff-record rec)
  2860.              diff-num (ediff-overlay-get overl 'ediff-diff-num))
  2861.            (ediff-set-overlay-face
  2862.         overl
  2863.         (if (not unhighlight)
  2864.             (ediff-background-face buf-type diff-num))
  2865.         )))
  2866.         diff-vector)))
  2867.        
  2868.  
  2869. ;;; Misc
  2870.  
  2871. ;; These two functions are here to neutralize XEmacs unwillingless to
  2872. ;; handle overlays whose buffers were deleted.
  2873. (defun ediff-move-overlay (overlay beg end &optional buffer)
  2874.   "Calls `move-overlay' in Emacs and `set-extent-endpoints' in Lemacs.
  2875. Checks if overlay's buffer exists before actually doing the move."
  2876.   (let ((buf (and overlay (ediff-overlay-buffer overlay))))
  2877.     (if (ediff-buffer-live-p buf)
  2878.     (if ediff-xemacs-p
  2879.         (set-extent-endpoints overlay beg end)
  2880.       (move-overlay overlay beg end buffer))
  2881.       ;; buffer's dead
  2882.       (if overlay
  2883.       (ediff-delete-overlay overlay)))))
  2884.       
  2885. (defun ediff-overlay-put (overlay prop value)
  2886.   "Calls `overlay-put' or `set-extent-property' depending on Emacs version.
  2887. Checks if overlay's buffer exists."
  2888.   (if (ediff-buffer-live-p (ediff-overlay-buffer overlay))
  2889.       (if ediff-xemacs-p
  2890.       (set-extent-property overlay prop value)
  2891.     (overlay-put overlay prop value))
  2892.     (ediff-delete-overlay overlay)))
  2893.     
  2894.  
  2895. ;; In Emacs, this just makes overlay. In the future, when Emacs will start
  2896. ;; supporting sticky overlays, this function will make a sticky overlay.
  2897. ;; BEG and END are expressions telling where overlay starts.
  2898. ;; If they are numbers or buffers, then all is well. Otherwise, they must
  2899. ;; be expressions to be evaluated in buffer BUF in order to get the overlay
  2900. ;; bounds.
  2901. ;; If BUFF is not a live buffer, then return nil; otherwise, return the
  2902. ;; newly created overlay.
  2903. (defun ediff-make-bullet-proof-overlay (beg end buff)
  2904.   (if (ediff-buffer-live-p buff)
  2905.       (let (overl)
  2906.     (ediff-eval-in-buffer buff
  2907.       (or (number-or-marker-p beg)
  2908.           (setq beg (eval beg)))
  2909.       (or (number-or-marker-p end)
  2910.           (setq end (eval end)))
  2911.       (setq overl (ediff-make-overlay beg end buff))
  2912.       
  2913.       (if ediff-xemacs-p
  2914.           (progn
  2915.         ;; take precautions against detached extents
  2916.         (ediff-overlay-put overl 'detachable nil) ; XEmacs
  2917.         (ediff-overlay-put overl 'evaporate nil)  ; Emacs
  2918.         ;; chars inserted at both ends will be inside extent
  2919.         (ediff-overlay-put overl 'start-open nil)
  2920.         (ediff-overlay-put overl 'end-open nil))
  2921.         (ediff-overlay-put overl 'ediff-diff-num 0)
  2922.         ;;(ediff-overlay-put overl 'insert-in-front-hooks
  2923.         ;;                 (list 'ediff-capture-inserts-in-front))
  2924.         ;;(ediff-overlay-put overl 'insert-behind-hooks
  2925.         ;;               (list 'ediff-capture-inserts-behind))
  2926.         ;; These two are not yet implemented in Emacs
  2927.         ;;(ediff-overlay-put overl 'rear-sticky t)
  2928.         ;;(ediff-overlay-put overl 'front-sticky t)
  2929.         )
  2930.       overl))))
  2931.       
  2932. (defsubst ediff-overlay-start (overl)
  2933.   (if (ediff-overlayp overl)
  2934.       (if ediff-emacs-p
  2935.       (overlay-start overl)
  2936.     (extent-start-position overl))))
  2937.     
  2938. (defsubst ediff-overlay-end  (overl)
  2939.   (if (ediff-overlayp overl)
  2940.       (if ediff-emacs-p
  2941.       (overlay-end overl)
  2942.     (extent-end-position overl))))
  2943.  
  2944.   
  2945. ;; Like other-buffer, but prefers visible buffers and ignores temporary or
  2946. ;; other insignificant buffers (those beginning with "^[ *]").
  2947. ;; Gets one arg--buffer name or a list of buffer names (it won't return
  2948. ;; these buffers).
  2949. (defun ediff-other-buffer (buff)
  2950.   (if (not (listp buff)) (setq buff (list buff)))
  2951.   (let* ((frame-buffers (buffer-list))
  2952.      (significant-buffers
  2953.       (mapcar
  2954.        (function (lambda (x)
  2955.                (cond ((member (buffer-name x) buff)
  2956.                   nil)
  2957.                  ((not (ediff-get-visible-buffer-window x))
  2958.                   nil)
  2959.                  ((string-match "^ " (buffer-name x))
  2960.                   nil)
  2961.                  (t x))))
  2962.        frame-buffers))
  2963.      (buffers (delq nil significant-buffers))
  2964.      less-significant-buffers)
  2965.      
  2966.     (cond (buffers (car buffers))
  2967.       ;; try also buffers that are not displayed in windows
  2968.       ((setq less-significant-buffers
  2969.          (delq nil
  2970.                (mapcar
  2971.             (function
  2972.              (lambda (x)
  2973.                (cond ((member (buffer-name x) buff) nil)
  2974.                  ((string-match "^[ *]" (buffer-name x)) nil)
  2975.                  (t x))))
  2976.             frame-buffers)))
  2977.        (car less-significant-buffers))
  2978.       (t (other-buffer (current-buffer))))
  2979.     ))
  2980.       
  2981.       
  2982. ;; Construct a unique buffer name.
  2983. ;; The first one tried is prefixsuffix, then prefix<2>suffix, 
  2984. ;; prefix<3>suffix, etc.
  2985. (defun ediff-unique-buffer-name (prefix suffix)
  2986.   (if (null (get-buffer (concat prefix suffix)))
  2987.       (concat prefix suffix)
  2988.     (let ((n 2))
  2989.       (while (get-buffer (format "%s<%d>%s" prefix n suffix))
  2990.     (setq n (1+ n)))
  2991.       (format "%s<%d>%s" prefix n suffix))))
  2992.   
  2993.  
  2994. (defun ediff-submit-report ()
  2995.   "Submit bug report on Ediff."
  2996.   (interactive)
  2997.   (let ((reporter-prompt-for-summary-p t)
  2998.     (ctl-buf ediff-control-buffer)
  2999.     (ediff-device-type (ediff-device-type))
  3000.     varlist salutation buffer-name)
  3001.     (setq varlist '(ediff-diff-program ediff-diff-options
  3002.             ediff-patch-program ediff-patch-options
  3003.             ediff-shell
  3004.             ediff-use-faces 
  3005.             ediff-auto-refine ediff-highlighting-style
  3006.             ediff-buffer-A ediff-buffer-B ediff-control-buffer
  3007.             ediff-forward-word-function
  3008.             ediff-control-frame
  3009.             ediff-control-frame-parameters
  3010.             ediff-control-frame-position-function
  3011.             ediff-prefer-iconified-control-frame
  3012.             ediff-window-setup-function
  3013.             ediff-split-window-function
  3014.             ediff-job-name
  3015.             ediff-word-mode
  3016.             buffer-name
  3017.             ediff-device-type
  3018.             ))
  3019.     (setq salutation "
  3020. Congratulations! You may have unearthed a bug in Ediff!
  3021.  
  3022. Please make a concise and accurate summary of what happened
  3023. and mail it to the address above.
  3024. -----------------------------------------------------------
  3025. ")
  3026.     
  3027.     (ediff-skip-unsuitable-frames)
  3028.     (ediff-reset-mouse)
  3029.     
  3030.     (switch-to-buffer ediff-msg-buffer)
  3031.     (erase-buffer)
  3032.     (delete-other-windows)
  3033.     (insert "
  3034. Please read this first:
  3035. ----------------------
  3036.  
  3037. Some ``bugs'' may actually be no bugs at all. For instance, if you are
  3038. reporting that certain difference regions are not matched as you think they
  3039. should, this is most likely due to the way Unix diff program decides what
  3040. constitutes a difference region. Ediff is an Emacs interface to diff, and
  3041. it has nothing to do with those decisions---it only takes the output from
  3042. diff and presents it in a way that is better suited for human browsing and
  3043. manipulation.
  3044.  
  3045. If Emacs happens to dump core, this is NOT an Ediff problem---it is
  3046. an Emacs bug. Report this to Emacs maintainers.
  3047.  
  3048. Another popular topic for reports is compilation messages.  Because Ediff
  3049. interfaces to several other packages and runs under Emacs and XEmacs,
  3050. byte-compilation may produce output like this:
  3051.  
  3052.        While compiling toplevel forms in file ediff.el:
  3053.      ** reference to free variable pm-color-alist
  3054.        ........................
  3055.        While compiling the end of the data:
  3056.      ** The following functions are not known to be defined: 
  3057.        ediff-valid-color-p, ediff-set-face,
  3058.        ........................
  3059.  
  3060. These are NOT errors, but inevitable warnings, which ought to be ignored.
  3061.  
  3062. Please do not report those and similar things.  However, comments and
  3063. suggestions are always welcome.
  3064.  
  3065. Mail anyway? (y or n) ")
  3066.       
  3067.     (if (y-or-n-p "Mail anyway? ")
  3068.     (progn
  3069.       (if (ediff-buffer-live-p ctl-buf)
  3070.           (set-buffer ctl-buf))
  3071.       (setq buffer-name (buffer-name))
  3072.       (require 'reporter)
  3073.       (reporter-submit-bug-report "kifer@cs.sunysb.edu"
  3074.                       (ediff-version)
  3075.                       varlist
  3076.                       nil 
  3077.                       'delete-other-windows
  3078.                       salutation))
  3079.       (bury-buffer)
  3080.       (beep 1)(message "Bug report aborted")
  3081.       (if (ediff-buffer-live-p ctl-buf)
  3082.       (ediff-eval-in-buffer ctl-buf
  3083.         (ediff-recenter 'no-rehighlight))))
  3084.     ))
  3085.                  
  3086.        
  3087. (defun ediff-deactivate-mark ()
  3088.   (if ediff-xemacs-p
  3089.       (zmacs-deactivate-region)
  3090.     (deactivate-mark)))
  3091.  
  3092. (cond ((fboundp 'nuke-selective-display)
  3093.        ;; XEmacs 19.12 has nuke-selective-display
  3094.        (fset 'ediff-nuke-selective-display 'nuke-selective-display))
  3095.       (t
  3096.        (defun ediff-nuke-selective-display ()
  3097.      (save-excursion
  3098.        (save-restriction
  3099.          (widen)
  3100.          (goto-char (point-min))
  3101.          (let ((mod-p (buffer-modified-p))
  3102.            buffer-read-only end)
  3103.            (and (eq t selective-display)
  3104.             (while (search-forward "\^M" nil t)
  3105.               (end-of-line)
  3106.               (setq end (point))
  3107.               (beginning-of-line)
  3108.               (while (search-forward "\^M" end t)
  3109.             (delete-char -1)
  3110.             (insert "\^J"))))
  3111.            (set-buffer-modified-p mod-p)
  3112.            (setq selective-display nil)))))
  3113.        ))
  3114.  
  3115.      
  3116. ;; The next two are modified versions from emerge.el.
  3117. ;; VARS must be a list of symbols
  3118. ;; ediff-save-variables returns an association list: ((var . val) ...)
  3119. (defsubst ediff-save-variables (vars)
  3120.   (mapcar (function (lambda (v) (cons v (symbol-value v))))
  3121.       vars))
  3122. ;; VARS is a list of variable symbols.
  3123. (defun ediff-restore-variables (vars assoc-list)
  3124.   (while vars
  3125.     (set (car vars) (cdr (assoc (car vars) assoc-list)))
  3126.     (setq vars (cdr vars))))
  3127.  
  3128. (defun ediff-change-saved-variable (var value buf-type)
  3129.   (let* ((assoc-list
  3130.       (symbol-value (intern
  3131.              (concat "ediff-buffer-values-orig-"
  3132.                  (symbol-name buf-type)))))
  3133.      (assoc-elt (assoc var assoc-list)))
  3134.   (if assoc-elt
  3135.       (setcdr assoc-elt value))))
  3136.   
  3137.   
  3138. ;; must execute in control buf
  3139. (defun ediff-save-protected-variables ()
  3140.   (setq ediff-buffer-values-orig-A
  3141.     (ediff-eval-in-buffer ediff-buffer-A
  3142.       (ediff-save-variables ediff-protected-variables)))
  3143.   (setq ediff-buffer-values-orig-B
  3144.     (ediff-eval-in-buffer ediff-buffer-B
  3145.       (ediff-save-variables ediff-protected-variables)))
  3146.   (if ediff-3way-comparison-job
  3147.       (setq ediff-buffer-values-orig-C
  3148.         (ediff-eval-in-buffer ediff-buffer-C
  3149.           (ediff-save-variables ediff-protected-variables))))
  3150.   (if (ediff-buffer-live-p ediff-ancestor-buffer)
  3151.       (setq ediff-buffer-values-orig-Ancestor
  3152.         (ediff-eval-in-buffer ediff-ancestor-buffer
  3153.           (ediff-save-variables ediff-protected-variables)))))
  3154.  
  3155. ;; must execute in control buf
  3156. (defun ediff-restore-protected-variables ()
  3157.   (let ((values-A ediff-buffer-values-orig-A)
  3158.     (values-B ediff-buffer-values-orig-B)
  3159.     (values-C ediff-buffer-values-orig-C)
  3160.     (values-Ancestor ediff-buffer-values-orig-Ancestor))
  3161.     (ediff-eval-in-buffer ediff-buffer-A
  3162.       (ediff-restore-variables ediff-protected-variables values-A))
  3163.     (ediff-eval-in-buffer ediff-buffer-B
  3164.       (ediff-restore-variables ediff-protected-variables values-B))
  3165.     (if ediff-3way-comparison-job
  3166.     (ediff-eval-in-buffer ediff-buffer-C
  3167.       (ediff-restore-variables ediff-protected-variables values-C)))
  3168.     (if (ediff-buffer-live-p ediff-ancestor-buffer)
  3169.     (ediff-eval-in-buffer ediff-ancestor-buffer
  3170.       (ediff-restore-variables ediff-protected-variables values-Ancestor)))
  3171.     ))
  3172.  
  3173.  
  3174. ;;; Debug
  3175.  
  3176. (ediff-defvar-local ediff-command-begin-time '(0 0 0) "")
  3177.  
  3178. ;; calculate time used by command
  3179. (defun ediff-calc-command-time ()
  3180.   (let ((end (current-time))
  3181.     micro sec)
  3182.     (setq micro
  3183.       (if (>= (nth 2 end) (nth 2 ediff-command-begin-time))
  3184.           (- (nth 2 end) (nth 2 ediff-command-begin-time))
  3185.         (+ (nth 2 end) (- 1000000 (nth 2 ediff-command-begin-time)))))
  3186.     (setq sec (- (nth 1 end) (nth 1 ediff-command-begin-time)))
  3187.     (or (equal ediff-command-begin-time '(0 0 0))
  3188.     (message "Elapsed time: %d second(s) + %d microsecond(s)" sec micro))))
  3189.  
  3190. (defsubst ediff-save-time ()
  3191.   (setq ediff-command-begin-time (current-time)))
  3192.     
  3193. (defun ediff-profile ()
  3194.   "Toggle profiling Ediff commands."
  3195.   (interactive)
  3196.   (or (ediff-buffer-live-p ediff-control-buffer)
  3197.       (error "This command runs only out of Ediff Control Buffer"))
  3198.   (if (memq 'ediff-save-time local-pre-command-hook)
  3199.       (progn (remove-hook 'local-pre-command-hook 'ediff-save-time)
  3200.          (remove-hook 'local-post-command-hook 'ediff-calc-command-time)
  3201.          (setq ediff-command-begin-time '(0 0 0))
  3202.          (message "Ediff profiling disabled"))
  3203.     (add-hook 'local-pre-command-hook 'ediff-save-time t)
  3204.     (add-hook 'local-post-command-hook 'ediff-calc-command-time)
  3205.     (message "Ediff profiling enabled")))
  3206.     
  3207. (defun ediff-print-diff-vector (diff-vector-var)
  3208.   (princ (format "\n*** %S ***\n" diff-vector-var))
  3209.   (mapcar (function
  3210.        (lambda (overl-vec)
  3211.          (princ
  3212.           (format
  3213.            "Diff %d: \tOverlay:    %S
  3214. \t\tFine diffs: %s
  3215. \t\tNo-fine-diff-flag: %S
  3216. \t\tState-of-diff:\t   %S
  3217. \t\tState-of-merge:\t   %S
  3218.            (1+ (ediff-overlay-get (aref overl-vec 0) 'ediff-diff-num))
  3219.            (aref overl-vec 0)
  3220.            ;; fine-diff-vector
  3221.            (if (= (length (aref overl-vec 1)) 0)
  3222.            "none\n"
  3223.          (mapconcat 'prin1-to-string
  3224.                 (aref overl-vec 1) "\n\t\t\t    "))
  3225.            (aref overl-vec 2) ; no fine diff flag
  3226.            (aref overl-vec 3) ; state-of-diff
  3227.            (aref overl-vec 4) ; state-of-merge
  3228.            ))))
  3229.       (eval diff-vector-var)))
  3230.  
  3231.   
  3232.  
  3233. (defun ediff-debug-info ()
  3234.   (interactive)
  3235.   (or (ediff-buffer-live-p ediff-control-buffer)
  3236.       (error "This command runs only out of Ediff Control Buffer"))
  3237.   (with-output-to-temp-buffer ediff-debug-buffer
  3238.     (princ (format "\nCtl buffer: %S\n" ediff-control-buffer))
  3239.     (ediff-print-diff-vector (intern "ediff-difference-vector-A"))
  3240.     (ediff-print-diff-vector (intern "ediff-difference-vector-B"))
  3241.     (ediff-print-diff-vector (intern "ediff-difference-vector-C"))
  3242.     (ediff-print-diff-vector (intern "ediff-difference-vector-Ancestor"))
  3243.     ))
  3244.  
  3245. ;; don't report error if version control package wasn't found
  3246. ;;(ediff-load-version-control 'silent)
  3247.  
  3248. (run-hooks 'ediff-load-hooks)
  3249.     
  3250.  
  3251. ;;; Local Variables:
  3252. ;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
  3253. ;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1)
  3254. ;;; End:
  3255.  
  3256. (provide 'ediff-util)
  3257.  
  3258. ;;; ediff-util.el ends here
  3259.